All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/9] Add support for imx8mm-venice-gw7901 and DSA switch
@ 2021-06-30 23:50 Tim Harvey
  2021-06-30 23:50 ` [PATCH 1/9] board: gateworks: venice: add imx8mm-gw7901 support Tim Harvey
                   ` (8 more replies)
  0 siblings, 9 replies; 25+ messages in thread
From: Tim Harvey @ 2021-06-30 23:50 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, Ramon Fried, u-boot, Vladimir Oltean,
	Claudiu Manoil, Michael Walle
  Cc: Tim Harvey

The GW7901 is an IMX8M Mini based board with a KSZ9897 switch hanging
off the IMX8M FEC.

In order to support a fixed-link connection to a U-Boot DSA switch some
changes need to be made to the FEC driver.

Additionally, in order to support per-port unique MAC addrs for DSA we
must introduce a mechanism to put the master device in promiscuous mode.

All patches are here including adding the dts for the board as well as a
dsa driver and necessary patches to fec/dsa so that it is clear how this
fits together.

Tim Harvey (9):
  board: gateworks: venice: add imx8mm-gw7901 support
  net: fec: use device sequence vs index when fetching fec
  net: fec: set phy_of_node properly for fixed-link phy
  net: add set_promisc function to enable/disable Promiscuous mode
  net: fec: add set_promisc function
  net: dsa: enable master promisc mode if available and needed
  net: add support for KSZ9477/KSZ9897/KSZ9567 GbE switch
  arm: dts: imx8mm-venice-gw7901.dts: fix dsa switch configuration
  configs: imx8mm_venice_defconfig: add support for gbe switch

 arch/arm/dts/Makefile                         |    1 +
 arch/arm/dts/imx8mm-venice-gw7901-u-boot.dtsi |  118 ++
 arch/arm/dts/imx8mm-venice-gw7901.dts         | 1055 +++++++++++++++++
 board/gateworks/venice/spl.c                  |   55 +-
 configs/imx8mm_venice_defconfig               |    6 +-
 drivers/net/Kconfig                           |    7 +
 drivers/net/Makefile                          |    1 +
 drivers/net/fec_mxc.c                         |   21 +-
 drivers/net/fec_mxc.h                         |    1 +
 drivers/net/ksz9477.c                         |  547 +++++++++
 include/net.h                                 |    2 +
 net/dsa-uclass.c                              |    9 +-
 12 files changed, 1818 insertions(+), 5 deletions(-)
 create mode 100644 arch/arm/dts/imx8mm-venice-gw7901-u-boot.dtsi
 create mode 100644 arch/arm/dts/imx8mm-venice-gw7901.dts
 create mode 100644 drivers/net/ksz9477.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 1/9] board: gateworks: venice: add imx8mm-gw7901 support
  2021-06-30 23:50 [PATCH 0/9] Add support for imx8mm-venice-gw7901 and DSA switch Tim Harvey
@ 2021-06-30 23:50 ` Tim Harvey
  2021-07-10 19:35   ` sbabic
  2021-06-30 23:50 ` [PATCH 2/9] net: fec: use device sequence vs index when fetching fec Tim Harvey
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 25+ messages in thread
From: Tim Harvey @ 2021-06-30 23:50 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, Ramon Fried, u-boot, Vladimir Oltean,
	Claudiu Manoil, Michael Walle
  Cc: Tim Harvey

The Gateworks GW7901 is an ARM based single board computer (SBC)
featuring:
 - i.MX8M Mini SoC
 - LPDDR4 DRAM
 - eMMC FLASH
 - SPI FRAM
 - Gateworks System Controller (GSC)
 - Atmel ATECC Crypto Authentication
 - USB 2.0
 - Microchip GbE Switch
 - Multiple multi-protocol RS232/RS485/RS422 Serial ports
 - onboard 802.11ac WiFi / BT
 - microSD socket
 - miniPCIe socket with PCIe, USB 2.0 and dual SIM sockets
 - Wide range DC power input
 - 802.3at PoE

To add support for this board:
 - add dts from Linux (accepted for v5.14)
 - add SPL PMIC config

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 arch/arm/dts/Makefile                         |    1 +
 arch/arm/dts/imx8mm-venice-gw7901-u-boot.dtsi |  118 ++
 arch/arm/dts/imx8mm-venice-gw7901.dts         | 1020 +++++++++++++++++
 board/gateworks/venice/spl.c                  |   55 +-
 configs/imx8mm_venice_defconfig               |    2 +-
 5 files changed, 1194 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/dts/imx8mm-venice-gw7901-u-boot.dtsi
 create mode 100644 arch/arm/dts/imx8mm-venice-gw7901.dts

diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 9fb38682e6..b390d6bf1a 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -861,6 +861,7 @@ dtb-$(CONFIG_ARCH_IMX8M) += \
 	imx8mm-venice-gw71xx-0x.dtb \
 	imx8mm-venice-gw72xx-0x.dtb \
 	imx8mm-venice-gw73xx-0x.dtb \
+	imx8mm-venice-gw7901.dtb \
 	imx8mm-verdin.dtb \
 	phycore-imx8mm.dtb \
 	imx8mn-ddr4-evk.dtb \
diff --git a/arch/arm/dts/imx8mm-venice-gw7901-u-boot.dtsi b/arch/arm/dts/imx8mm-venice-gw7901-u-boot.dtsi
new file mode 100644
index 0000000000..3b24ca638a
--- /dev/null
+++ b/arch/arm/dts/imx8mm-venice-gw7901-u-boot.dtsi
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2020 Gateworks Corporation
+ */
+
+&{/soc@0} {
+	u-boot,dm-pre-reloc;
+	u-boot,dm-spl;
+};
+
+&clk {
+	u-boot,dm-spl;
+	u-boot,dm-pre-reloc;
+	/delete-property/ assigned-clocks;
+	/delete-property/ assigned-clock-parents;
+	/delete-property/ assigned-clock-rates;
+};
+
+&osc_24m {
+	u-boot,dm-spl;
+	u-boot,dm-pre-reloc;
+};
+
+&aips1 {
+	u-boot,dm-spl;
+	u-boot,dm-pre-reloc;
+};
+
+&aips2 {
+	u-boot,dm-spl;
+};
+
+&aips3 {
+	u-boot,dm-spl;
+};
+
+&iomuxc {
+	u-boot,dm-spl;
+};
+
+&gpio1 {
+	u-boot,dm-spl;
+};
+
+&gpio2 {
+	u-boot,dm-spl;
+};
+
+&gpio3 {
+	u-boot,dm-spl;
+};
+
+&gpio4 {
+	u-boot,dm-spl;
+};
+
+&gpio5 {
+	u-boot,dm-spl;
+};
+
+&uart2 {
+	u-boot,dm-spl;
+};
+
+&pinctrl_uart2 {
+	u-boot,dm-spl;
+};
+
+&usdhc2 {
+	u-boot,dm-spl;
+};
+
+&pinctrl_usdhc2 {
+	u-boot,dm-spl;
+};
+
+&usdhc3 {
+	u-boot,dm-spl;
+};
+
+&pinctrl_usdhc3 {
+	u-boot,dm-spl;
+};
+
+&i2c1 {
+	u-boot,dm-spl;
+};
+
+&pinctrl_i2c1 {
+	u-boot,dm-spl;
+};
+
+&i2c2 {
+	u-boot,dm-spl;
+};
+
+&pinctrl_i2c2 {
+	u-boot,dm-spl;
+};
+
+&fec1 {
+	phy-reset-gpios = <&gpio4 19 GPIO_ACTIVE_LOW>;
+	phy-reset-duration = <1>;
+	phy-reset-post-delay = <1>;
+};
+
+&{/soc@0/bus@30800000/i2c@30a30000/pmic@4b} {
+	u-boot,dm-spl;
+};
+
+&{/soc@0/bus@30800000/i2c@30a30000/pmic@4b/regulators} {
+	u-boot,dm-spl;
+};
+
+&pinctrl_pmic {
+	u-boot,dm-spl;
+};
+
diff --git a/arch/arm/dts/imx8mm-venice-gw7901.dts b/arch/arm/dts/imx8mm-venice-gw7901.dts
new file mode 100644
index 0000000000..0216facb2a
--- /dev/null
+++ b/arch/arm/dts/imx8mm-venice-gw7901.dts
@@ -0,0 +1,1020 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2020 Gateworks Corporation
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/leds/common.h>
+
+#include "imx8mm.dtsi"
+
+/ {
+	model = "Gateworks Venice GW7901 i.MX8MM board";
+	compatible = "gw,imx8mm-gw7901", "fsl,imx8mm";
+
+	aliases {
+		ethernet0 = &fec1;
+		ethernet1 = &lan1;
+		ethernet2 = &lan2;
+		ethernet3 = &lan3;
+		ethernet4 = &lan4;
+		usb0 = &usbotg1;
+		usb1 = &usbotg2;
+	};
+
+	chosen {
+		stdout-path = &uart2;
+	};
+
+	memory@40000000 {
+		device_type = "memory";
+		reg = <0x0 0x40000000 0 0x80000000>;
+	};
+
+	gpio-keys {
+		compatible = "gpio-keys";
+
+		user-pb {
+			label = "user_pb";
+			gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
+			linux,code = <BTN_0>;
+		};
+
+		user-pb1x {
+			label = "user_pb1x";
+			linux,code = <BTN_1>;
+			interrupt-parent = <&gsc>;
+			interrupts = <0>;
+		};
+
+		key-erased {
+			label = "key_erased";
+			linux,code = <BTN_2>;
+			interrupt-parent = <&gsc>;
+			interrupts = <1>;
+		};
+
+		eeprom-wp {
+			label = "eeprom_wp";
+			linux,code = <BTN_3>;
+			interrupt-parent = <&gsc>;
+			interrupts = <2>;
+		};
+
+		tamper {
+			label = "tamper";
+			linux,code = <BTN_4>;
+			interrupt-parent = <&gsc>;
+			interrupts = <5>;
+		};
+
+		switch-hold {
+			label = "switch_hold";
+			linux,code = <BTN_5>;
+			interrupt-parent = <&gsc>;
+			interrupts = <7>;
+		};
+	};
+
+	led-controller {
+		compatible = "gpio-leds";
+
+		led-0 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_RED>;
+			label = "led01_red";
+			gpios = <&leds_gpio 0 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-1 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_GREEN>;
+			label = "led01_grn";
+			gpios = <&leds_gpio 1 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-2 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_RED>;
+			label = "led02_red";
+			gpios = <&leds_gpio 2 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-3 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_GREEN>;
+			label = "led02_grn";
+			gpios = <&leds_gpio 3 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-4 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_RED>;
+			label = "led03_red";
+			gpios = <&leds_gpio 4 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-5 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_GREEN>;
+			label = "led03_grn";
+			gpios = <&leds_gpio 5 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-6 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_RED>;
+			label = "led04_red";
+			gpios = <&leds_gpio 8 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-7 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_GREEN>;
+			label = "led04_grn";
+			gpios = <&leds_gpio 9 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-8 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_RED>;
+			label = "led05_red";
+			gpios = <&leds_gpio 10 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-9 {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_GREEN>;
+			label = "led05_grn";
+			gpios = <&leds_gpio 11 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-a {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_RED>;
+			label = "led06_red";
+			gpios = <&leds_gpio 12 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+
+		led-b {
+			function = LED_FUNCTION_STATUS;
+			color = <LED_COLOR_ID_GREEN>;
+			label = "led06_grn";
+			gpios = <&leds_gpio 13 GPIO_ACTIVE_HIGH>;
+			default-state = "off";
+		};
+	};
+
+	reg_3p3v: regulator-3p3v {
+		compatible = "regulator-fixed";
+		regulator-name = "3P3V";
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+
+	regulator-ioexp {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_reg_ioexp>;
+		compatible = "regulator-fixed";
+		regulator-name = "ioexp";
+		gpio = <&gpio4 21 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		startup-delay-us = <100>;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	regulator-isouart {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_reg_isouart>;
+		compatible = "regulator-fixed";
+		regulator-name = "iso_uart";
+		gpio = <&gpio1 13 GPIO_ACTIVE_LOW>;
+		startup-delay-us = <100>;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+		regulator-always-on;
+	};
+
+	reg_usb2_vbus: regulator-usb2 {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_reg_usb2>;
+		compatible = "regulator-fixed";
+		regulator-name = "usb_usb2_vbus";
+		gpio = <&gpio4 2 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		regulator-min-microvolt = <5000000>;
+		regulator-max-microvolt = <5000000>;
+	};
+
+	reg_wifi: regulator-wifi {
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_reg_wl>;
+		compatible = "regulator-fixed";
+		regulator-name = "wifi";
+		gpio = <&gpio3 25 GPIO_ACTIVE_HIGH>;
+		enable-active-high;
+		startup-delay-us = <100>;
+		regulator-min-microvolt = <3300000>;
+		regulator-max-microvolt = <3300000>;
+	};
+};
+
+&ddrc {
+	operating-points-v2 = <&ddrc_opp_table>;
+
+	ddrc_opp_table: opp-table {
+		compatible = "operating-points-v2";
+
+		opp-25M {
+			opp-hz = /bits/ 64 <25000000>;
+		};
+
+		opp-100M {
+			opp-hz = /bits/ 64 <100000000>;
+		};
+
+		opp-750M {
+			opp-hz = /bits/ 64 <750000000>;
+		};
+	};
+};
+
+&ecspi1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_spi1>;
+	cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
+	status = "okay";
+
+	flash@0 {
+		compatible = "jedec,spi-nor";
+		reg = <0>;
+		spi-max-frequency = <40000000>;
+		status = "okay";
+	};
+};
+
+&fec1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_fec1>;
+	phy-mode = "rgmii-id";
+	local-mac-address = [00 00 00 00 00 00];
+	status = "okay";
+
+	fixed-link {
+		speed = <1000>;
+		full-duplex;
+	};
+};
+
+&i2c1 {
+	clock-frequency = <100000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c1>;
+	status = "okay";
+
+	gsc: gsc@20 {
+		compatible = "gw,gsc";
+		reg = <0x20>;
+		pinctrl-0 = <&pinctrl_gsc>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
+		interrupt-controller;
+		#interrupt-cells = <1>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		adc {
+			compatible = "gw,gsc-adc";
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			channel@6 {
+				gw,mode = <0>;
+				reg = <0x06>;
+				label = "temp";
+			};
+
+			channel@8 {
+				gw,mode = <1>;
+				reg = <0x08>;
+				label = "vdd_bat";
+			};
+
+			channel@82 {
+				gw,mode = <2>;
+				reg = <0x82>;
+				label = "vin_aux1";
+				gw,voltage-divider-ohms = <22100 1000>;
+			};
+
+			channel@84 {
+				gw,mode = <2>;
+				reg = <0x84>;
+				label = "vin_aux2";
+				gw,voltage-divider-ohms = <22100 1000>;
+			};
+
+			channel@86 {
+				gw,mode = <2>;
+				reg = <0x86>;
+				label = "vdd_vin";
+				gw,voltage-divider-ohms = <22100 1000>;
+			};
+
+			channel@88 {
+				gw,mode = <2>;
+				reg = <0x88>;
+				label = "vdd_3p3";
+				gw,voltage-divider-ohms = <10000 10000>;
+			};
+
+			channel@8c {
+				gw,mode = <2>;
+				reg = <0x8c>;
+				label = "vdd_2p5";
+				gw,voltage-divider-ohms = <10000 10000>;
+			};
+
+			channel@8e {
+				gw,mode = <2>;
+				reg = <0x8e>;
+				label = "vdd_0p95";
+			};
+
+			channel@90 {
+				gw,mode = <2>;
+				reg = <0x90>;
+				label = "vdd_soc";
+			};
+
+			channel@92 {
+				gw,mode = <2>;
+				reg = <0x92>;
+				label = "vdd_arm";
+			};
+
+			channel@98 {
+				gw,mode = <2>;
+				reg = <0x98>;
+				label = "vdd_1p8";
+			};
+
+			channel@9a {
+				gw,mode = <2>;
+				reg = <0x9a>;
+				label = "vdd_1p2";
+			};
+
+			channel@9c {
+				gw,mode = <2>;
+				reg = <0x9c>;
+				label = "vdd_dram";
+			};
+
+			channel@a2 {
+				gw,mode = <2>;
+				reg = <0xa2>;
+				label = "vdd_gsc";
+				gw,voltage-divider-ohms = <10000 10000>;
+			};
+		};
+	};
+
+	gpio: gpio@23 {
+		compatible = "nxp,pca9555";
+		reg = <0x23>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-parent = <&gsc>;
+		interrupts = <4>;
+	};
+
+	eeprom@50 {
+		compatible = "atmel,24c02";
+		reg = <0x50>;
+		pagesize = <16>;
+	};
+
+	eeprom@51 {
+		compatible = "atmel,24c02";
+		reg = <0x51>;
+		pagesize = <16>;
+	};
+
+	eeprom@52 {
+		compatible = "atmel,24c02";
+		reg = <0x52>;
+		pagesize = <16>;
+	};
+
+	eeprom@53 {
+		compatible = "atmel,24c02";
+		reg = <0x53>;
+		pagesize = <16>;
+	};
+
+	rtc@68 {
+		compatible = "dallas,ds1672";
+		reg = <0x68>;
+	};
+};
+
+&i2c2 {
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c2>;
+	status = "okay";
+
+	pmic@4b {
+		compatible = "rohm,bd71847";
+		reg = <0x4b>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&pinctrl_pmic>;
+		interrupt-parent = <&gpio3>;
+		interrupts = <20 IRQ_TYPE_LEVEL_LOW>;
+		rohm,reset-snvs-powered;
+		#clock-cells = <0>;
+		clocks = <&osc_32k 0>;
+		clock-output-names = "clk-32k-out";
+
+		regulators {
+			/* vdd_soc: 0.805-0.900V (typ=0.8V) */
+			BUCK1 {
+				regulator-name = "buck1";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <1250>;
+			};
+
+			/* vdd_arm: 0.805-1.0V (typ=0.9V) */
+			BUCK2 {
+				regulator-name = "buck2";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1300000>;
+				regulator-boot-on;
+				regulator-always-on;
+				regulator-ramp-delay = <1250>;
+				rohm,dvs-run-voltage = <1000000>;
+				rohm,dvs-idle-voltage = <900000>;
+			};
+
+			/* vdd_0p9: 0.805-1.0V (typ=0.9V) */
+			BUCK3 {
+				regulator-name = "buck3";
+				regulator-min-microvolt = <700000>;
+				regulator-max-microvolt = <1350000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* vdd_3p3 */
+			BUCK4 {
+				regulator-name = "buck4";
+				regulator-min-microvolt = <3000000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* vdd_1p8 */
+			BUCK5 {
+				regulator-name = "buck5";
+				regulator-min-microvolt = <1605000>;
+				regulator-max-microvolt = <1995000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* vdd_dram */
+			BUCK6 {
+				regulator-name = "buck6";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <1400000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* nvcc_snvs_1p8 */
+			LDO1 {
+				regulator-name = "ldo1";
+				regulator-min-microvolt = <1600000>;
+				regulator-max-microvolt = <1900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* vdd_snvs_0p8 */
+			LDO2 {
+				regulator-name = "ldo2";
+				regulator-min-microvolt = <800000>;
+				regulator-max-microvolt = <900000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			/* vdda_1p8 */
+			LDO3 {
+				regulator-name = "ldo3";
+				regulator-min-microvolt = <1800000>;
+				regulator-max-microvolt = <3300000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			LDO4 {
+				regulator-name = "ldo4";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+
+			LDO6 {
+				regulator-name = "ldo6";
+				regulator-min-microvolt = <900000>;
+				regulator-max-microvolt = <1800000>;
+				regulator-boot-on;
+				regulator-always-on;
+			};
+		};
+	};
+};
+
+&i2c3 {
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c3>;
+	status = "okay";
+
+	leds_gpio: gpio@20 {
+		compatible = "nxp,pca9555";
+		reg = <0x20>;
+		gpio-controller;
+		#gpio-cells = <2>;
+	};
+
+	switch: switch@5f {
+		compatible = "microchip,ksz9897";
+		reg = <0x5f>;
+		pinctrl-0 = <&pinctrl_ksz>;
+		interrupt-parent = <&gpio4>;
+		interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
+		phy-mode = "rgmii-id";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			lan1: port@0 {
+				reg = <0>;
+				label = "lan1";
+				local-mac-address = [00 00 00 00 00 00];
+			};
+
+			lan2: port@1 {
+				reg = <1>;
+				label = "lan2";
+				local-mac-address = [00 00 00 00 00 00];
+			};
+
+			lan3: port@2 {
+				reg = <2>;
+				label = "lan3";
+				local-mac-address = [00 00 00 00 00 00];
+			};
+
+			lan4: port@3 {
+				reg = <3>;
+				label = "lan4";
+				local-mac-address = [00 00 00 00 00 00];
+			};
+
+			port@5 {
+				reg = <5>;
+				label = "cpu";
+				ethernet = <&fec1>;
+				phy-mode = "rgmii-id";
+
+				fixed-link {
+					speed = <1000>;
+					full-duplex;
+				};
+			};
+		};
+	};
+
+	crypto@60 {
+		compatible = "atmel,atecc508a";
+		reg = <0x60>;
+	};
+};
+
+&i2c4 {
+	clock-frequency = <400000>;
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_i2c4>;
+	status = "okay";
+};
+
+&uart1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart1>, <&pinctrl_uart1_gpio>;
+	rts-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
+	cts-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>;
+	dtr-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
+	dsr-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
+	dcd-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+/* console */
+&uart2 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart2>;
+	status = "okay";
+};
+
+&uart3 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart3>, <&pinctrl_uart3_gpio>;
+	cts-gpios = <&gpio4 10 GPIO_ACTIVE_LOW>;
+	rts-gpios = <&gpio4 9 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&uart4 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_uart4>, <&pinctrl_uart4_gpio>;
+	cts-gpios = <&gpio5 11 GPIO_ACTIVE_LOW>;
+	rts-gpios = <&gpio5 12 GPIO_ACTIVE_LOW>;
+	status = "okay";
+};
+
+&usbotg1 {
+	dr_mode = "host";
+	disable-over-current;
+	status = "okay";
+};
+
+&usbotg2 {
+	dr_mode = "host";
+	vbus-supply = <&reg_usb2_vbus>;
+	status = "okay";
+};
+
+/* SDIO WiFi */
+&usdhc1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_usdhc1>;
+	bus-width = <4>;
+	non-removable;
+	vmmc-supply = <&reg_wifi>;
+	status = "okay";
+};
+
+/* microSD */
+&usdhc2 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+	pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+	cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+	bus-width = <4>;
+	vmmc-supply = <&reg_3p3v>;
+	status = "okay";
+};
+
+/* eMMC */
+&usdhc3 {
+	pinctrl-names = "default", "state_100mhz", "state_200mhz";
+	pinctrl-0 = <&pinctrl_usdhc3>;
+	pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+	pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+	bus-width = <8>;
+	non-removable;
+	status = "okay";
+};
+
+&wdog1 {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_wdog>;
+	fsl,ext-reset-output;
+	status = "okay";
+};
+
+&iomuxc {
+	pinctrl-names = "default";
+	pinctrl-0 = <&pinctrl_hog>;
+
+	pinctrl_hog: hoggrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SPDIF_TX_GPIO5_IO3		0x40000041 /* DIG2_OUT */
+			MX8MM_IOMUXC_SPDIF_RX_GPIO5_IO4		0x40000041 /* DIG2_IN */
+			MX8MM_IOMUXC_GPIO1_IO06_GPIO1_IO6	0x40000041 /* DIG1_IN */
+			MX8MM_IOMUXC_GPIO1_IO07_GPIO1_IO7	0x40000041 /* DIG1_OUT */
+			MX8MM_IOMUXC_SAI3_RXD_GPIO4_IO30	0x40000041 /* SIM2DET# */
+			MX8MM_IOMUXC_SAI3_RXC_GPIO4_IO29	0x40000041 /* SIM1DET# */
+			MX8MM_IOMUXC_SPDIF_EXT_CLK_GPIO5_IO5	0x40000041 /* SIM2SEL */
+		>;
+	};
+
+	pinctrl_fec1: fec1grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_ENET_MDC_ENET1_MDC			0x3
+			MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO		0x3
+			MX8MM_IOMUXC_ENET_TD3_ENET1_RGMII_TD3		0x1f
+			MX8MM_IOMUXC_ENET_TD2_ENET1_RGMII_TD2		0x1f
+			MX8MM_IOMUXC_ENET_TD1_ENET1_RGMII_TD1		0x1f
+			MX8MM_IOMUXC_ENET_TD0_ENET1_RGMII_TD0		0x1f
+			MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3		0x91
+			MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2		0x91
+			MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1		0x91
+			MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0		0x91
+			MX8MM_IOMUXC_ENET_TXC_ENET1_RGMII_TXC		0x1f
+			MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC		0x91
+			MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL	0x91
+			MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL	0x1f
+			MX8MM_IOMUXC_SAI1_TXD6_GPIO4_IO18		0x19 /* IRQ# */
+			MX8MM_IOMUXC_SAI1_TXD7_GPIO4_IO19		0x19 /* RST# */
+		>;
+	};
+
+	pinctrl_gsc: gscgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SAI1_TXD4_GPIO4_IO16	0x159
+		>;
+	};
+
+	pinctrl_i2c1: i2c1grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL		0x400001c3
+			MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA		0x400001c3
+		>;
+	};
+
+	pinctrl_i2c2: i2c2grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL		0x400001c3
+			MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA		0x400001c3
+		>;
+	};
+
+	pinctrl_i2c3: i2c3grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL		0x400001c3
+			MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA		0x400001c3
+		>;
+	};
+
+	pinctrl_i2c4: i2c4grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL		0x400001c3
+			MX8MM_IOMUXC_I2C4_SDA_I2C4_SDA		0x400001c3
+		>;
+	};
+
+	pinctrl_ksz: kszgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SAI1_TXD6_GPIO4_IO18	0x41
+			MX8MM_IOMUXC_SAI1_TXD7_GPIO4_IO19	0x41 /* RST# */
+		>;
+	};
+
+	pinctrl_pmic: pmicgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SAI5_RXC_GPIO3_IO20	0x41
+		>;
+	};
+
+	pinctrl_reg_isouart: regisouartgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_GPIO1_IO13_GPIO1_IO13	0x40000041
+		>;
+	};
+
+	pinctrl_reg_ioexp: regioexpgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SAI2_RXFS_GPIO4_IO21	0x40000041
+		>;
+	};
+
+	pinctrl_reg_wl: regwlgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SAI5_MCLK_GPIO3_IO25	0x40000041
+		>;
+	};
+
+	pinctrl_reg_usb2: regusb1grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SAI1_RXD0_GPIO4_IO2	0x41
+			MX8MM_IOMUXC_SAI1_TXD5_GPIO4_IO17	0x140
+			MX8MM_IOMUXC_GPIO1_IO15_USB2_OTG_OC	0x140
+		>;
+	};
+
+	pinctrl_spi1: spi1grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_ECSPI1_SCLK_ECSPI1_SCLK	0x82
+			MX8MM_IOMUXC_ECSPI1_MOSI_ECSPI1_MOSI	0x82
+			MX8MM_IOMUXC_ECSPI1_MISO_ECSPI1_MISO	0x82
+			MX8MM_IOMUXC_ECSPI1_SS0_GPIO5_IO9	0x140
+		>;
+	};
+
+	pinctrl_uart1: uart1grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_UART1_RXD_UART1_DCE_RX	0x140
+			MX8MM_IOMUXC_UART1_TXD_UART1_DCE_TX	0x140
+			MX8MM_IOMUXC_GPIO1_IO01_GPIO1_IO1	0x140
+			MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10	0x140
+			MX8MM_IOMUXC_GPIO1_IO11_GPIO1_IO11	0x140
+			MX8MM_IOMUXC_GPIO1_IO12_GPIO1_IO12	0x140
+			MX8MM_IOMUXC_GPIO1_IO14_GPIO1_IO14	0x140
+		>;
+	};
+
+	pinctrl_uart1_gpio: uart1gpiogrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_GPIO1_IO00_GPIO1_IO0	0x40000041 /* RS422# */
+			MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3	0x40000041 /* RS485# */
+			MX8MM_IOMUXC_GPIO1_IO05_GPIO1_IO5	0x40000041 /* RS232# */
+		>;
+	};
+
+	pinctrl_uart2: uart2grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX	0x140
+			MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX	0x140
+		>;
+	};
+
+	pinctrl_uart3: uart3grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_UART3_RXD_UART3_DCE_RX	0x140
+			MX8MM_IOMUXC_UART3_TXD_UART3_DCE_TX	0x140
+			MX8MM_IOMUXC_SAI1_RXD7_GPIO4_IO9	0x140
+			MX8MM_IOMUXC_SAI1_TXFS_GPIO4_IO10	0x140
+		>;
+	};
+
+	pinctrl_uart3_gpio: uart3gpiogrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SAI1_RXD4_GPIO4_IO6	0x40000110 /* RS232# */
+			MX8MM_IOMUXC_SAI1_RXD5_GPIO4_IO7	0x40000110 /* RS422# */
+			MX8MM_IOMUXC_SAI1_RXD6_GPIO4_IO8	0x40000110 /* RS485# */
+		>;
+	};
+
+	pinctrl_uart4: uart4grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_UART4_RXD_UART4_DCE_RX	0x140
+			MX8MM_IOMUXC_UART4_TXD_UART4_DCE_TX	0x140
+			MX8MM_IOMUXC_ECSPI2_MOSI_GPIO5_IO11	0x140
+			MX8MM_IOMUXC_ECSPI2_MISO_GPIO5_IO12	0x140
+		>;
+	};
+
+	pinctrl_uart4_gpio: uart4gpiogrp {
+		fsl,pins = <
+
+			MX8MM_IOMUXC_ECSPI2_SCLK_GPIO5_IO10	0x40000041 /* RS232# */
+			MX8MM_IOMUXC_ECSPI2_SS0_GPIO5_IO13	0x40000041 /* RS422# */
+			MX8MM_IOMUXC_SAI2_MCLK_GPIO4_IO27	0x40000041 /* RS485# */
+		>;
+	};
+
+	pinctrl_usdhc1: usdhc1grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK		0x190
+			MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD		0x1d0
+			MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0	0x1d0
+			MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1	0x1d0
+			MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2	0x1d0
+			MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3	0x1d0
+		>;
+	};
+
+	pinctrl_usdhc2: usdhc2grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK		0x190
+			MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD		0x1d0
+			MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0	0x1d0
+			MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1	0x1d0
+			MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2	0x1d0
+			MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3	0x1d0
+		>;
+	};
+
+	pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK		0x194
+			MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD		0x1d4
+			MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0	0x1d4
+			MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1	0x1d4
+			MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2	0x1d4
+			MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3	0x1d4
+		>;
+	};
+
+	pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK		0x196
+			MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD		0x1d6
+			MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0	0x1d6
+			MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1	0x1d6
+			MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2	0x1d6
+			MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3	0x1d6
+		>;
+	};
+
+	pinctrl_usdhc2_gpio: usdhc2-gpiogrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12	0x1c4
+			MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT  0x1d0
+		>;
+	};
+
+	pinctrl_usdhc3: usdhc3grp {
+		fsl,pins = <
+			MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK	0x190
+			MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD	0x1d0
+			MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0	0x1d0
+			MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1	0x1d0
+			MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2	0x1d0
+			MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3	0x1d0
+			MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4	0x1d0
+			MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5	0x1d0
+			MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6	0x1d0
+			MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7	0x1d0
+			MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE	0x190
+		>;
+	};
+
+	pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK	0x194
+			MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD	0x1d4
+			MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0	0x1d4
+			MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1	0x1d4
+			MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2	0x1d4
+			MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3	0x1d4
+			MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4	0x1d4
+			MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5	0x1d4
+			MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6	0x1d4
+			MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7	0x1d4
+			MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE	0x194
+		>;
+	};
+
+	pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_NAND_WE_B_USDHC3_CLK	0x196
+			MX8MM_IOMUXC_NAND_WP_B_USDHC3_CMD	0x1d6
+			MX8MM_IOMUXC_NAND_DATA04_USDHC3_DATA0	0x1d6
+			MX8MM_IOMUXC_NAND_DATA05_USDHC3_DATA1	0x1d6
+			MX8MM_IOMUXC_NAND_DATA06_USDHC3_DATA2	0x1d6
+			MX8MM_IOMUXC_NAND_DATA07_USDHC3_DATA3	0x1d6
+			MX8MM_IOMUXC_NAND_RE_B_USDHC3_DATA4	0x1d6
+			MX8MM_IOMUXC_NAND_CE2_B_USDHC3_DATA5	0x1d6
+			MX8MM_IOMUXC_NAND_CE3_B_USDHC3_DATA6	0x1d6
+			MX8MM_IOMUXC_NAND_CLE_USDHC3_DATA7	0x1d6
+			MX8MM_IOMUXC_NAND_CE1_B_USDHC3_STROBE	0x196
+		>;
+	};
+
+	pinctrl_wdog: wdoggrp {
+		fsl,pins = <
+			MX8MM_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B	0xc6
+		>;
+	};
+};
+
+&cpu_alert0 {
+	temperature = <95000>;
+	hysteresis = <2000>;
+	type = "passive";
+};
+
+&cpu_crit0 {
+	temperature = <105000>;
+	hysteresis = <2000>;
+	type = "critical";
+};
diff --git a/board/gateworks/venice/spl.c b/board/gateworks/venice/spl.c
index ea500d4f81..8c357757c1 100644
--- a/board/gateworks/venice/spl.c
+++ b/board/gateworks/venice/spl.c
@@ -26,6 +26,7 @@
 #include <dm/uclass-internal.h>
 #include <dm/device-internal.h>
 
+#include <power/bd71837.h>
 #include <power/mp5416.h>
 
 #include "gsc.h"
@@ -88,8 +89,23 @@ int board_early_init_f(void)
  * Note that we can not use pmic dm drivers here as we have a generic
  * venice dt that does not have board-specific pmic's defined.
  *
- * Instead we must use dm_i2c.
+ * Instead we must use dm_i2c so we a helpers to give us
+ * clrsetbit functions we would otherwise have if we could use PMIC dm
+ * drivers.
  */
+static int dm_i2c_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
+{
+	int ret;
+	u8 val;
+
+	ret = dm_i2c_read(dev, reg, &val, 1);
+	if (ret)
+		return ret;
+	val = (val & ~clr) | set;
+
+	return dm_i2c_write(dev, reg, &val, 1);
+}
+
 static int power_init_board(void)
 {
 	const char *model = gsc_get_model();
@@ -117,6 +133,43 @@ static int power_init_board(void)
 				 BIT(7) | MP5416_VSET_SW3_SVAL(920000));
 	}
 
+	else if (!strncmp(model, "GW7901", 6)) {
+		ret = uclass_get_device_by_name(UCLASS_I2C, "i2c@30a30000", &bus);
+		if (ret) {
+			printf("PMIC    : failed I2C2 probe: %d\n", ret);
+			return ret;
+		}
+		ret = dm_i2c_probe(bus, 0x4b, 0, &dev);
+		if (ret) {
+			printf("PMIC    : failed probe: %d\n", ret);
+			return ret;
+		}
+		puts("PMIC    : BD71847\n");
+
+		/* unlock the PMIC regs */
+		dm_i2c_reg_write(dev, BD718XX_REGLOCK, 0x1);
+
+		/* set switchers to forced PWM mode */
+		dm_i2c_clrsetbits(dev, BD718XX_BUCK1_CTRL, 0, 0x8);
+		dm_i2c_clrsetbits(dev, BD718XX_BUCK2_CTRL, 0, 0x8);
+		dm_i2c_clrsetbits(dev, BD718XX_1ST_NODVS_BUCK_CTRL, 0, 0x8);
+		dm_i2c_clrsetbits(dev, BD718XX_2ND_NODVS_BUCK_CTRL, 0, 0x8);
+		dm_i2c_clrsetbits(dev, BD718XX_3RD_NODVS_BUCK_CTRL, 0, 0x8);
+		dm_i2c_clrsetbits(dev, BD718XX_4TH_NODVS_BUCK_CTRL, 0, 0x8);
+
+		/* increase VDD_0P95 (VDD_GPU/VPU/DRAM) to 0.975v for 1.5Ghz DDR */
+		dm_i2c_reg_write(dev, BD718XX_1ST_NODVS_BUCK_VOLT, 0x83);
+
+		/* increase VDD_SOC to 0.85v before first DRAM access */
+		dm_i2c_reg_write(dev, BD718XX_BUCK1_VOLT_RUN, 0x0f);
+
+		/* increase VDD_ARM to 0.92v for 800 and 1600Mhz */
+		dm_i2c_reg_write(dev, BD718XX_BUCK2_VOLT_RUN, 0x16);
+
+		/* Lock the PMIC regs */
+		dm_i2c_reg_write(dev, BD718XX_REGLOCK, 0x11);
+	}
+
 	return 0;
 }
 
diff --git a/configs/imx8mm_venice_defconfig b/configs/imx8mm_venice_defconfig
index daffcc46d5..3961db00cb 100644
--- a/configs/imx8mm_venice_defconfig
+++ b/configs/imx8mm_venice_defconfig
@@ -58,7 +58,7 @@ CONFIG_CMD_EXT4_WRITE=y
 # CONFIG_SPL_EFI_PARTITION is not set
 CONFIG_OF_CONTROL=y
 CONFIG_SPL_OF_CONTROL=y
-CONFIG_OF_LIST="imx8mm-venice-gw71xx-0x imx8mm-venice-gw72xx-0x imx8mm-venice-gw73xx-0x"
+CONFIG_OF_LIST="imx8mm-venice-gw71xx-0x imx8mm-venice-gw72xx-0x imx8mm-venice-gw73xx-0x imx8mm-venice-gw7901"
 CONFIG_ENV_IS_IN_MMC=y
 CONFIG_SYS_REDUNDAND_ENVIRONMENT=y
 CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG=y
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 2/9] net: fec: use device sequence vs index when fetching fec
  2021-06-30 23:50 [PATCH 0/9] Add support for imx8mm-venice-gw7901 and DSA switch Tim Harvey
  2021-06-30 23:50 ` [PATCH 1/9] board: gateworks: venice: add imx8mm-gw7901 support Tim Harvey
@ 2021-06-30 23:50 ` Tim Harvey
  2021-07-02  9:44   ` Ramon Fried
  2021-07-10 19:35   ` sbabic
  2021-06-30 23:50 ` [PATCH 3/9] net: fec: set phy_of_node properly for fixed-link phy Tim Harvey
                   ` (6 subsequent siblings)
  8 siblings, 2 replies; 25+ messages in thread
From: Tim Harvey @ 2021-06-30 23:50 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, Ramon Fried, u-boot, Vladimir Oltean,
	Claudiu Manoil, Michael Walle
  Cc: Tim Harvey

When using uclass_get_device* to get the FEC device we need to use
device sequence instead of index into UCLASS_ETH. In systems where for
example a I2C based DSA switch exists it will probe before the FEC
master and its ports will be registered first and have the first
indexes yet the FEC's sequence comes from the device-tree alias.

Take for example the imx8mm-venice-gw7901 board which has an i2c based
DSA switch:

u-boot=> net list
eth1 : lan1 00:0d:8d:aa:00:2f
eth2 : lan2 00:0d:8d:aa:00:30
eth3 : lan3 00:0d:8d:aa:00:31
eth4 : lan4 00:0d:8d:aa:00:32
eth0 : ethernet@30be0000 00:0d:8d:aa:00:2e active

Thus in this case uclass_get_device(UCLASS_ETH, 0, &dev) returns lan1
which is wrong but uclass_get_device_seq(UCLASS_ETH, 0, &dev) returns
ethernet@30be000 which is correct.

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 drivers/net/fec_mxc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 4fd5c01b4a..3abf914833 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -146,7 +146,7 @@ static int fec_get_clk_rate(void *udev, int idx)
 	    CONFIG_IS_ENABLED(CLK_CCF)) {
 		dev = udev;
 		if (!dev) {
-			ret = uclass_get_device(UCLASS_ETH, idx, &dev);
+			ret = uclass_get_device_by_seq(UCLASS_ETH, idx, &dev);
 			if (ret < 0) {
 				debug("Can't get FEC udev: %d\n", ret);
 				return ret;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 3/9] net: fec: set phy_of_node properly for fixed-link phy
  2021-06-30 23:50 [PATCH 0/9] Add support for imx8mm-venice-gw7901 and DSA switch Tim Harvey
  2021-06-30 23:50 ` [PATCH 1/9] board: gateworks: venice: add imx8mm-gw7901 support Tim Harvey
  2021-06-30 23:50 ` [PATCH 2/9] net: fec: use device sequence vs index when fetching fec Tim Harvey
@ 2021-06-30 23:50 ` Tim Harvey
  2021-07-02  9:44   ` Ramon Fried
  2021-07-10 19:34   ` sbabic
  2021-06-30 23:50 ` [PATCH 4/9] net: add set_promisc function to enable/disable Promiscuous mode Tim Harvey
                   ` (5 subsequent siblings)
  8 siblings, 2 replies; 25+ messages in thread
From: Tim Harvey @ 2021-06-30 23:50 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, Ramon Fried, u-boot, Vladimir Oltean,
	Claudiu Manoil, Michael Walle
  Cc: Tim Harvey

If the FEC is connected to a fixed-link (upstream switch port for
example) the phy_of_node should be set to the fixed-link node
so that speed and other properties can be found properly.

In addition fix a typo in the debug string.

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 drivers/net/fec_mxc.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 3abf914833..77680491d0 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -1304,7 +1304,11 @@ static int device_get_phy_addr(struct fec_priv *priv, struct udevice *dev)
 	ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
 					 &phandle_args);
 	if (ret) {
-		debug("Failed to find phy-handle (err = %d\n)", ret);
+		priv->phy_of_node = ofnode_find_subnode(dev_ofnode(dev),
+							"fixed-link");
+		if (ofnode_valid(priv->phy_of_node))
+			return 0;
+		debug("Failed to find phy-handle (err = %d)\n", ret);
 		return ret;
 	}
 
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 4/9] net: add set_promisc function to enable/disable Promiscuous mode
  2021-06-30 23:50 [PATCH 0/9] Add support for imx8mm-venice-gw7901 and DSA switch Tim Harvey
                   ` (2 preceding siblings ...)
  2021-06-30 23:50 ` [PATCH 3/9] net: fec: set phy_of_node properly for fixed-link phy Tim Harvey
@ 2021-06-30 23:50 ` Tim Harvey
  2021-07-02  9:46   ` Ramon Fried
  2021-07-10 19:36   ` sbabic
  2021-06-30 23:50 ` [PATCH 5/9] net: fec: add set_promisc function Tim Harvey
                   ` (4 subsequent siblings)
  8 siblings, 2 replies; 25+ messages in thread
From: Tim Harvey @ 2021-06-30 23:50 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, Ramon Fried, u-boot, Vladimir Oltean,
	Claudiu Manoil, Michael Walle
  Cc: Tim Harvey

Enabling promiscuous mode can be useful for DSA switches where each port
has its own MAC address.

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 include/net.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/net.h b/include/net.h
index b95d6a6f60..cec8c98618 100644
--- a/include/net.h
+++ b/include/net.h
@@ -158,6 +158,7 @@ enum eth_recv_flags {
  *		    ROM on the board. This is how the driver should expose it
  *		    to the network stack. This function should fill in the
  *		    eth_pdata::enetaddr field - optional
+ * set_promisc: Enable or Disable promiscuous mode
  */
 struct eth_ops {
 	int (*start)(struct udevice *dev);
@@ -168,6 +169,7 @@ struct eth_ops {
 	int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
 	int (*write_hwaddr)(struct udevice *dev);
 	int (*read_rom_hwaddr)(struct udevice *dev);
+	int (*set_promisc)(struct udevice *dev, bool enable);
 };
 
 #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 5/9] net: fec: add set_promisc function
  2021-06-30 23:50 [PATCH 0/9] Add support for imx8mm-venice-gw7901 and DSA switch Tim Harvey
                   ` (3 preceding siblings ...)
  2021-06-30 23:50 ` [PATCH 4/9] net: add set_promisc function to enable/disable Promiscuous mode Tim Harvey
@ 2021-06-30 23:50 ` Tim Harvey
  2021-07-02  9:46   ` Ramon Fried
  2021-07-10 19:35   ` sbabic
  2021-06-30 23:50 ` [PATCH 6/9] net: dsa: enable master promisc mode if available and needed Tim Harvey
                   ` (3 subsequent siblings)
  8 siblings, 2 replies; 25+ messages in thread
From: Tim Harvey @ 2021-06-30 23:50 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, Ramon Fried, u-boot, Vladimir Oltean,
	Claudiu Manoil, Michael Walle
  Cc: Tim Harvey

Enabling promiscuous mode is necessary if FEC is the master of a DSA
switch driver where each port has their own MAC address.

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 drivers/net/fec_mxc.c | 13 +++++++++++++
 drivers/net/fec_mxc.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
index 77680491d0..db2cdaf684 100644
--- a/drivers/net/fec_mxc.c
+++ b/drivers/net/fec_mxc.c
@@ -458,6 +458,9 @@ static void fec_reg_setup(struct fec_priv *fec)
 	else if (fec->xcv_type == RMII)
 		rcntrl |= FEC_RCNTRL_RMII;
 
+	if (fec->promisc)
+		rcntrl |= 0x8;
+
 	writel(rcntrl, &fec->eth->r_cntrl);
 }
 
@@ -1278,6 +1281,15 @@ static int fecmxc_read_rom_hwaddr(struct udevice *dev)
 	return fec_get_hwaddr(priv->dev_id, pdata->enetaddr);
 }
 
+static int fecmxc_set_promisc(struct udevice *dev, bool enable)
+{
+	struct fec_priv *priv = dev_get_priv(dev);
+
+	priv->promisc = enable;
+
+	return 0;
+}
+
 static int fecmxc_free_pkt(struct udevice *dev, uchar *packet, int length)
 {
 	if (packet)
@@ -1294,6 +1306,7 @@ static const struct eth_ops fecmxc_ops = {
 	.stop			= fecmxc_halt,
 	.write_hwaddr		= fecmxc_set_hwaddr,
 	.read_rom_hwaddr	= fecmxc_read_rom_hwaddr,
+	.set_promisc		= fecmxc_set_promisc,
 };
 
 static int device_get_phy_addr(struct fec_priv *priv, struct udevice *dev)
diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
index 5ccde9193b..62b55ef395 100644
--- a/drivers/net/fec_mxc.h
+++ b/drivers/net/fec_mxc.h
@@ -272,6 +272,7 @@ struct fec_priv {
 	struct clk clk_ref;
 	struct clk clk_ptp;
 	u32 clk_rate;
+	char promisc;
 };
 
 /**
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 6/9] net: dsa: enable master promisc mode if available and needed
  2021-06-30 23:50 [PATCH 0/9] Add support for imx8mm-venice-gw7901 and DSA switch Tim Harvey
                   ` (4 preceding siblings ...)
  2021-06-30 23:50 ` [PATCH 5/9] net: fec: add set_promisc function Tim Harvey
@ 2021-06-30 23:50 ` Tim Harvey
  2021-07-02  9:47   ` Ramon Fried
  2021-07-10 19:35   ` sbabic
  2021-06-30 23:50 ` [PATCH 7/9] net: add support for KSZ9477/KSZ9897/KSZ9567 GbE switch Tim Harvey
                   ` (2 subsequent siblings)
  8 siblings, 2 replies; 25+ messages in thread
From: Tim Harvey @ 2021-06-30 23:50 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, Ramon Fried, u-boot, Vladimir Oltean,
	Claudiu Manoil, Michael Walle
  Cc: Tim Harvey

If ports have their own unique MAC addrs and master has a set_promisc
function, call it so that packets will be received for ports.

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 net/dsa-uclass.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c
index 7ea1cb6949..694664d81b 100644
--- a/net/dsa-uclass.c
+++ b/net/dsa-uclass.c
@@ -277,8 +277,15 @@ static int dsa_port_probe(struct udevice *pdev)
 	 * has a unique MAC address specified in the environment.
 	 */
 	eth_env_get_enetaddr_by_index("eth", dev_seq(pdev), env_enetaddr);
-	if (!is_zero_ethaddr(env_enetaddr))
+	if (!is_zero_ethaddr(env_enetaddr)) {
+		/* individual port mac addrs require master to be promisc */
+		struct eth_ops *eth_ops = eth_get_ops(master);
+
+		if (eth_ops->set_promisc)
+			eth_ops->set_promisc(master, 1);
+
 		return 0;
+	}
 
 	master_pdata = dev_get_plat(master);
 	eth_pdata = dev_get_plat(pdev);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 7/9] net: add support for KSZ9477/KSZ9897/KSZ9567 GbE switch
  2021-06-30 23:50 [PATCH 0/9] Add support for imx8mm-venice-gw7901 and DSA switch Tim Harvey
                   ` (5 preceding siblings ...)
  2021-06-30 23:50 ` [PATCH 6/9] net: dsa: enable master promisc mode if available and needed Tim Harvey
@ 2021-06-30 23:50 ` Tim Harvey
  2021-07-02  9:49   ` Ramon Fried
  2021-07-10 19:35   ` sbabic
  2021-06-30 23:50 ` [PATCH 8/9] arm: dts: imx8mm-venice-gw7901.dts: fix dsa switch configuration Tim Harvey
  2021-06-30 23:50 ` [PATCH 9/9] configs: imx8mm_venice_defconfig: add support for gbe switch Tim Harvey
  8 siblings, 2 replies; 25+ messages in thread
From: Tim Harvey @ 2021-06-30 23:50 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, Ramon Fried, u-boot, Vladimir Oltean,
	Claudiu Manoil, Michael Walle
  Cc: Tim Harvey

The Microchip KSZ9477/KSZ9897/KSZ9567 7-Port Gigabit Ethernet Switches
support SGMII/RGMII/MII/RMII with register access via SPI, I2C, or MDIO.

This driver currently supports I2C register access but SPI or MDIO register
access can be easily added at a later time.

Tagging is not implemented and instead the active port is tracked to
avoid needing a tag to store port information.

This was tested with the imx8mm-venice-gw7901 board which has a
KSZ9897S switch with an IMX8MM FEC MAC master connected via RGMII_ID.

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 drivers/net/Kconfig   |   7 +
 drivers/net/Makefile  |   1 +
 drivers/net/ksz9477.c | 547 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 555 insertions(+)
 create mode 100644 drivers/net/ksz9477.c

diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 9fc28b149d..feeea960e2 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -402,6 +402,13 @@ config KS8851_MLL_BASEADDR
 endif #DM_ETH
 endif #KS8851_MLL
 
+config KSZ9477
+	bool "Microchip KSZ9477 I2C controller driver"
+	depends on DM_DSA && DM_I2C
+	help
+	  This driver implements a DSA switch driver for the KSZ9477 family
+	  of GbE switches using the I2C interface.
+
 config MVGBE
 	bool "Marvell Orion5x/Kirkwood network interface support"
 	depends on ARCH_KIRKWOOD || ARCH_ORION5X
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index d56baa65b2..03900ffa3a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_FTMAC110) += ftmac110.o
 obj-$(CONFIG_FTMAC100) += ftmac100.o
 obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o
 obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
+obj-$(CONFIG_KSZ9477) += ksz9477.o
 obj-$(CONFIG_LAN91C96) += lan91c96.o
 obj-$(CONFIG_LPC32XX_ETH) += lpc32xx_eth.o
 obj-$(CONFIG_MACB) += macb.o
diff --git a/drivers/net/ksz9477.c b/drivers/net/ksz9477.c
new file mode 100644
index 0000000000..ab32f42127
--- /dev/null
+++ b/drivers/net/ksz9477.c
@@ -0,0 +1,547 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020
+ * Tim Harvey, Gateworks Corporation
+ */
+
+#include <dm.h>
+#include <dm/device_compat.h>
+#include <dm/device-internal.h>
+#include <dm/lists.h>
+#include <eth_phy.h>
+#include <linux/delay.h>
+#include <miiphy.h>
+#include <i2c.h>
+#include <net/dsa.h>
+
+#include <asm-generic/gpio.h>
+
+/* Global registers */
+
+/* Chip ID */
+#define REG_CHIP_ID0__1			0x0000
+
+/* Operation control */
+#define REG_SW_OPERATION		0x0300
+#define SW_RESET			BIT(1)
+#define SW_START			BIT(0)
+
+/* Port Specific Registers */
+#define PORT_CTRL_ADDR(port, addr) ((addr) | (((port) + 1) << 12))
+
+/* Port Control */
+#define REG_PORT_XMII_CTRL_1		0x0301
+#define PORT_MII_NOT_1GBIT		BIT(6)
+#define PORT_MII_SEL_EDGE		BIT(5)
+#define PORT_RGMII_ID_IG_ENABLE		BIT(4)
+#define PORT_RGMII_ID_EG_ENABLE		BIT(3)
+#define PORT_MII_MAC_MODE		BIT(2)
+#define PORT_MII_SEL_M			0x3
+#define PORT_RGMII_SEL			0x0
+#define PORT_RMII_SEL			0x1
+#define PORT_GMII_SEL			0x2
+#define PORT_MII_SEL			0x3
+
+/* Port MSTP State Register */
+#define REG_PORT_MSTP_STATE		0x0b04
+#define PORT_TX_ENABLE			BIT(2)
+#define PORT_RX_ENABLE			BIT(1)
+#define PORT_LEARN_DISABLE		BIT(0)
+
+/* MMD */
+#define REG_PORT_PHY_MMD_SETUP		0x011A
+#define PORT_MMD_OP_MODE_M		0x3
+#define PORT_MMD_OP_MODE_S		14
+#define PORT_MMD_OP_INDEX		0
+#define PORT_MMD_OP_DATA_NO_INCR	1
+#define PORT_MMD_OP_DATA_INCR_RW	2
+#define PORT_MMD_OP_DATA_INCR_W		3
+#define PORT_MMD_DEVICE_ID_M		0x1F
+#define MMD_SETUP(mode, dev)		(((u16)(mode) << PORT_MMD_OP_MODE_S) | (dev))
+#define REG_PORT_PHY_MMD_INDEX_DATA	0x011C
+
+struct ksz_dsa_priv {
+	struct udevice *dev;
+	int active_port;
+};
+
+static inline int ksz_read8(struct udevice *dev, u32 reg, u8 *val)
+{
+	int ret = dm_i2c_read(dev, reg, val, 1);
+
+	dev_dbg(dev, "%s 0x%04x<<0x%02x\n", __func__, reg, *val);
+
+	return ret;
+}
+
+static inline int ksz_pread8(struct udevice *dev, int port, int reg, u8 *val)
+{
+	return ksz_read8(dev, PORT_CTRL_ADDR(port, reg), val);
+}
+
+static inline int ksz_write8(struct udevice *dev, u32 reg, u8 val)
+{
+	dev_dbg(dev, "%s 0x%04x>>0x%02x\n", __func__, reg, val);
+	return dm_i2c_write(dev, reg, &val, 1);
+}
+
+static inline int ksz_pwrite8(struct udevice *dev, int port, int reg, u8 val)
+{
+	return ksz_write8(dev, PORT_CTRL_ADDR(port, reg), val);
+}
+
+static inline int ksz_write16(struct udevice *dev, u32 reg, u16 val)
+{
+	u8 buf[2];
+
+	buf[1] = val & 0xff;
+	buf[0] = val >> 8;
+	dev_dbg(dev, "%s 0x%04x>>0x%04x\n", __func__, reg, val);
+
+	return dm_i2c_write(dev, reg, buf, 2);
+}
+
+static inline int ksz_pwrite16(struct udevice *dev, int port, int reg, u16 val)
+{
+	return ksz_write16(dev, PORT_CTRL_ADDR(port, reg), val);
+}
+
+static inline int ksz_read16(struct udevice *dev, u32 reg, u16 *val)
+{
+	u8 buf[2];
+	int ret;
+
+	ret = dm_i2c_read(dev, reg, buf, 2);
+	*val = (buf[0] << 8) | buf[1];
+	dev_dbg(dev, "%s 0x%04x<<0x%04x\n", __func__, reg, *val);
+
+	return ret;
+}
+
+static inline int ksz_pread16(struct udevice *dev, int port, int reg, u16 *val)
+{
+	return ksz_read16(dev, PORT_CTRL_ADDR(port, reg), val);
+}
+
+static inline int ksz_read32(struct udevice *dev, u32 reg, u32 *val)
+{
+	return dm_i2c_read(dev, reg, (u8 *)val, 4);
+}
+
+static inline int ksz_pread32(struct udevice *dev, int port, int reg, u32 *val)
+{
+	return ksz_read32(dev, PORT_CTRL_ADDR(port, reg), val);
+}
+
+static inline int ksz_write32(struct udevice *dev, u32 reg, u32 val)
+{
+	u8 buf[4];
+
+	buf[3] = val & 0xff;
+	buf[2] = (val >> 24) & 0xff;
+	buf[1] = (val >> 16) & 0xff;
+	buf[0] = (val >> 8) & 0xff;
+	dev_dbg(dev, "%s 0x%04x>>0x%04x\n", __func__, reg, val);
+
+	return dm_i2c_write(dev, reg, buf, 4);
+}
+
+static inline int ksz_pwrite32(struct udevice *dev, int port, int reg, u32 val)
+{
+	return ksz_write32(dev, PORT_CTRL_ADDR(port, reg), val);
+}
+
+static __maybe_unused void ksz_port_mmd_read(struct udevice *dev, int port,
+					     u8 addr, u16 reg, u16 *val)
+{
+	ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_INDEX, addr));
+	ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, reg);
+	ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, addr));
+	ksz_pread16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
+	dev_dbg(dev, "%s  P%d 0x%02x:0x%04x<<0x%04x\n", __func__, port + 1, addr, reg, *val);
+}
+
+static void ksz_port_mmd_write(struct udevice *dev, int port, u8 addr, u16 reg, u16 val)
+{
+	dev_dbg(dev, "%s P%d 0x%02x:0x%04x>>0x%04x\n", __func__, port + 1, addr, addr, val);
+	ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_INDEX, addr));
+	ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, addr);
+	ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, addr));
+	ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
+}
+
+/* Apply PHY settings to address errata listed in KSZ9477, KSZ9897, KSZ9896, KSZ9567
+ * Silicon Errata and Data Sheet Clarification documents
+ */
+static void ksz_phy_errata_setup(struct udevice *dev, int port)
+{
+	dev_dbg(dev, "%s P%d\n", __func__, port + 1);
+
+	/* Register settings are needed to improve PHY receive performance */
+	ksz_port_mmd_write(dev, port, 0x01, 0x6f, 0xdd0b);
+	ksz_port_mmd_write(dev, port, 0x01, 0x8f, 0x6032);
+	ksz_port_mmd_write(dev, port, 0x01, 0x9d, 0x248c);
+	ksz_port_mmd_write(dev, port, 0x01, 0x75, 0x0060);
+	ksz_port_mmd_write(dev, port, 0x01, 0xd3, 0x7777);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x06, 0x3008);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x08, 0x2001);
+
+	/* Transmit waveform amplitude can be improved (1000BASE-T, 100BASE-TX, 10BASE-Te) */
+	ksz_port_mmd_write(dev, port, 0x1c, 0x04, 0x00d0);
+
+	/* Energy Efficient Ethernet (EEE) feature select must be manually disabled */
+	ksz_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000);
+
+	/* Register settings are required to meet data sheet supply current specifications */
+	ksz_port_mmd_write(dev, port, 0x1c, 0x13, 0x6eff);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x14, 0xe6ff);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x15, 0x6eff);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x16, 0xe6ff);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x17, 0x00ff);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x18, 0x43ff);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x19, 0xc3ff);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x1a, 0x6fff);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x1b, 0x07ff);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x1c, 0x0fff);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x1d, 0xe7ff);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x1e, 0xefff);
+	ksz_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee);
+}
+
+/*
+ * mii bus driver
+ */
+#define KSZ_MDIO_CHILD_DRV_NAME	"ksz_mdio"
+
+struct ksz_mdio_priv {
+	struct ksz_dsa_priv *ksz;
+};
+
+static int dm_ksz_mdio_read(struct udevice *dev, int addr, int devad, int reg)
+{
+	struct ksz_mdio_priv *priv = dev_get_priv(dev);
+	struct ksz_dsa_priv *ksz = priv->ksz;
+	u16 val = 0xffff;
+
+	ksz_pread16(ksz->dev, addr, 0x100 + (reg << 1), &val);
+	dev_dbg(ksz->dev, "%s P%d reg=0x%04x:0x%04x<<0x%04x\n", __func__,
+		addr + 1, reg, 0x100 + (reg << 1), val);
+
+	return val;
+};
+
+static int dm_ksz_mdio_write(struct udevice *dev, int addr, int devad, int reg, u16 val)
+{
+	struct ksz_mdio_priv *priv = dev_get_priv(dev);
+	struct ksz_dsa_priv *ksz = priv->ksz;
+
+	dev_dbg(ksz->dev, "%s P%d reg=0x%04x:%04x>>0x%04x\n",
+		__func__, addr + 1, reg, 0x100 + (reg << 1), val);
+	ksz_pwrite16(ksz->dev, addr, 0x100 + (reg << 1), val);
+
+	return 0;
+}
+
+static const struct mdio_ops ksz_mdio_ops = {
+	.read = dm_ksz_mdio_read,
+	.write = dm_ksz_mdio_write,
+};
+
+static int ksz_mdio_bind(struct udevice *dev)
+{
+	char name[16];
+	static int num_devices;
+
+	dev_dbg(dev, "%s\n", __func__);
+	sprintf(name, "ksz-mdio-%d", num_devices++);
+	device_set_name(dev, name);
+
+	return 0;
+}
+
+static int ksz_mdio_probe(struct udevice *dev)
+{
+	struct ksz_mdio_priv *priv = dev_get_priv(dev);
+
+	dev_dbg(dev, "%s\n", __func__);
+	priv->ksz = dev_get_parent_priv(dev->parent);
+
+	return 0;
+}
+
+static const struct udevice_id ksz_mdio_ids[] = {
+	{ .compatible = "microchip,ksz-mdio" },
+	{ }
+};
+
+U_BOOT_DRIVER(ksz_mdio) = {
+	.name		= KSZ_MDIO_CHILD_DRV_NAME,
+	.id		= UCLASS_MDIO,
+	.of_match	= ksz_mdio_ids,
+	.bind		= ksz_mdio_bind,
+	.probe		= ksz_mdio_probe,
+	.ops		= &ksz_mdio_ops,
+	.priv_auto	= sizeof(struct ksz_mdio_priv),
+	.plat_auto	= sizeof(struct mdio_perdev_priv),
+};
+
+static int ksz_port_setup(struct udevice *dev, int port,
+			  phy_interface_t interface)
+{
+	struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
+	u8 data8;
+
+	dev_dbg(dev, "%s P%d %s\n", __func__, port + 1,
+		(port == pdata->cpu_port) ? "cpu" : "");
+
+	if (port != pdata->cpu_port) {
+		/* phy port: config errata and leds */
+		ksz_phy_errata_setup(dev, port);
+	} else {
+		/* cpu port: configure MAC interface mode */
+		ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
+		dev_dbg(dev, "%s P%d cpu interface %s\n", __func__, port + 1,
+			phy_string_for_interface(interface));
+		switch (interface) {
+		case PHY_INTERFACE_MODE_MII:
+			data8 &= ~PORT_MII_SEL_M;
+			data8 |= PORT_MII_SEL;
+			data8 |= PORT_MII_NOT_1GBIT;
+			break;
+		case PHY_INTERFACE_MODE_RMII:
+			data8 &= ~PORT_MII_SEL_M;
+			data8 |= PORT_RMII_SEL;
+			data8 |= PORT_MII_NOT_1GBIT;
+			break;
+		case PHY_INTERFACE_MODE_GMII:
+			data8 &= ~PORT_MII_SEL_M;
+			data8 |= PORT_GMII_SEL;
+			data8 &= ~PORT_MII_NOT_1GBIT;
+			break;
+		default:
+			data8 &= ~PORT_MII_SEL_M;
+			data8 |= PORT_RGMII_SEL;
+			data8 &= ~PORT_MII_NOT_1GBIT;
+			data8 &= ~PORT_RGMII_ID_IG_ENABLE;
+			data8 &= ~PORT_RGMII_ID_EG_ENABLE;
+			if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
+			    interface == PHY_INTERFACE_MODE_RGMII_RXID)
+				data8 |= PORT_RGMII_ID_IG_ENABLE;
+			if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
+			    interface == PHY_INTERFACE_MODE_RGMII_TXID)
+				data8 |= PORT_RGMII_ID_EG_ENABLE;
+			break;
+		}
+		ksz_write8(dev, PORT_CTRL_ADDR(port, REG_PORT_XMII_CTRL_1), data8);
+	}
+
+	return 0;
+}
+
+static int ksz_port_enable(struct udevice *dev, int port, struct phy_device *phy)
+{
+	struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
+	struct ksz_dsa_priv *priv = dev_get_priv(dev);
+	int supported = PHY_GBIT_FEATURES;
+	u8 data8;
+	int ret;
+
+	dev_dbg(dev, "%s P%d 0x%x %s\n", __func__, port + 1, phy->phy_id,
+		phy_string_for_interface(phy->interface));
+
+	/* setup this port */
+	ret = ksz_port_setup(dev, port, phy->interface);
+	if (ret) {
+		dev_err(dev, "port setup failed: %d\n", ret);
+		return ret;
+	}
+
+	/* enable port forwarding for this port */
+	ksz_pread8(priv->dev, port, REG_PORT_MSTP_STATE, &data8);
+	data8 &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
+	data8 |= (PORT_TX_ENABLE | PORT_RX_ENABLE);
+	ksz_pwrite8(priv->dev, port, REG_PORT_MSTP_STATE, data8);
+
+	/* if cpu master we are done */
+	if (port == pdata->cpu_port)
+		return 0;
+
+	/* configure phy */
+	phy->supported &= supported;
+	phy->advertising &= supported;
+	ret = phy_config(phy);
+	if (ret)
+		return ret;
+
+	ret = phy_startup(phy);
+	if (ret)
+		return ret;
+
+	/* start switch */
+	ksz_read8(priv->dev, REG_SW_OPERATION, &data8);
+	data8 |= SW_START;
+	ksz_write8(priv->dev, REG_SW_OPERATION, data8);
+
+	/* keep track of current enabled non-cpu port */
+	priv->active_port = port;
+
+	return 0;
+}
+
+static void ksz_port_disable(struct udevice *dev, int port, struct phy_device *phy)
+{
+	struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
+	struct ksz_dsa_priv *priv = dev_get_priv(dev);
+	u8 data8;
+
+	dev_dbg(dev, "%s P%d 0x%x\n", __func__, port + 1, phy->phy_id);
+
+	/* can't disable CPU port without re-configuring/re-starting switch */
+	if (port == pdata->cpu_port)
+		return;
+
+	/* disable port */
+	ksz_pread8(priv->dev, port, REG_PORT_MSTP_STATE, &data8);
+	data8 &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
+	data8 |= PORT_LEARN_DISABLE;
+	ksz_pwrite8(priv->dev, port, REG_PORT_MSTP_STATE, data8);
+
+	/*
+	 * we don't call phy_shutdown here to avoid waiting next time we use
+	 * the port, but the downside is that remote side will think we're
+	 * actively processing traffic although we are not.
+	 */
+}
+
+static int ksz_xmit(struct udevice *dev, int port, void *packet, int length)
+{
+	dev_dbg(dev, "%s P%d %d\n", __func__, port + 1, length);
+
+	return 0;
+}
+
+static int ksz_recv(struct udevice *dev, int *port, void *packet, int length)
+{
+	struct ksz_dsa_priv *priv = dev_get_priv(dev);
+
+	dev_dbg(dev, "%s P%d %d\n", __func__, priv->active_port + 1, length);
+	*port = priv->active_port;
+
+	return 0;
+};
+
+static const struct dsa_ops ksz_dsa_ops = {
+	.port_enable = ksz_port_enable,
+	.port_disable = ksz_port_disable,
+	.xmit = ksz_xmit,
+	.rcv = ksz_recv,
+};
+
+static int ksz_probe_mdio(struct udevice *dev)
+{
+	ofnode node, mdios;
+	int ret;
+
+	mdios = dev_read_subnode(dev, "mdios");
+	if (ofnode_valid(mdios)) {
+		ofnode_for_each_subnode(node, mdios) {
+			const char *name = ofnode_get_name(node);
+			struct udevice *pdev;
+
+			ret = device_bind_driver_to_node(dev,
+							 KSZ_MDIO_CHILD_DRV_NAME,
+							 name, node, &pdev);
+			if (ret)
+				dev_err(dev, "failed to probe %s: %d\n", name, ret);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * I2C driver
+ */
+static int ksz_i2c_probe(struct udevice *dev)
+{
+	struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
+	struct ksz_dsa_priv *priv = dev_get_priv(dev);
+	struct udevice *master = dsa_get_master(dev);
+	int i, ret;
+	u8 data8;
+	u32 id;
+
+	if (!master)
+		return -ENODEV;
+
+	dev_dbg(dev, "%s %s master:%s\n", __func__, dev->name, master->name);
+	dev_set_parent_priv(dev, priv);
+
+	ret = i2c_set_chip_offset_len(dev, 2);
+	if (ret) {
+		printf("i2c_set_chip_offset_len failed: %d\n", ret);
+		return ret;
+	}
+
+	/* default config */
+	priv->dev = dev;
+
+	/* chip level reset */
+	ksz_read8(priv->dev, REG_SW_OPERATION, &data8);
+	data8 |= SW_RESET;
+	ksz_write8(priv->dev, REG_SW_OPERATION, data8);
+
+	/* read chip id */
+	ret = ksz_read32(dev, REG_CHIP_ID0__1, &id);
+	if (ret)
+		return ret;
+	id = __swab32(id);
+	dev_dbg(dev, "%s id=0x%08x\n", __func__, id);
+	switch (id & 0xffffff00) {
+	case 0x00947700:
+		puts("KSZ9477S: ");
+		break;
+	case 0x00956700:
+		puts("KSZ9567R: ");
+		break;
+	case 0x00989700:
+		puts("KSZ9897S: ");
+		break;
+	default:
+		dev_err(dev, "invalid chip id: 0x%08x\n", id);
+		return -EINVAL;
+	}
+
+	/* probe mdio bus */
+	ret = ksz_probe_mdio(dev);
+	if (ret)
+		return ret;
+
+	/* disable ports by default */
+	for (i = 0; i < pdata->num_ports; i++) {
+		ksz_pread8(priv->dev, i, REG_PORT_MSTP_STATE, &data8);
+		data8 &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
+		ksz_pwrite8(priv->dev, i, REG_PORT_MSTP_STATE, data8);
+	}
+
+	dsa_set_tagging(dev, 0, 0);
+
+	return 0;
+};
+
+static const struct udevice_id ksz_i2c_ids[] = {
+	{ .compatible = "microchip,ksz9897" },
+	{ .compatible = "microchip,ksz9477" },
+	{ .compatible = "microchip,ksz9567" },
+	{ }
+};
+
+U_BOOT_DRIVER(ksz) = {
+	.name		= "ksz-switch",
+	.id		= UCLASS_DSA,
+	.of_match	= ksz_i2c_ids,
+	.probe		= ksz_i2c_probe,
+	.ops		= &ksz_dsa_ops,
+	.priv_auto	= sizeof(struct ksz_dsa_priv),
+};
+
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 8/9] arm: dts: imx8mm-venice-gw7901.dts: fix dsa switch configuration
  2021-06-30 23:50 [PATCH 0/9] Add support for imx8mm-venice-gw7901 and DSA switch Tim Harvey
                   ` (6 preceding siblings ...)
  2021-06-30 23:50 ` [PATCH 7/9] net: add support for KSZ9477/KSZ9897/KSZ9567 GbE switch Tim Harvey
@ 2021-06-30 23:50 ` Tim Harvey
  2021-07-10 19:35   ` sbabic
  2021-06-30 23:50 ` [PATCH 9/9] configs: imx8mm_venice_defconfig: add support for gbe switch Tim Harvey
  8 siblings, 1 reply; 25+ messages in thread
From: Tim Harvey @ 2021-06-30 23:50 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, Ramon Fried, u-boot, Vladimir Oltean,
	Claudiu Manoil, Michael Walle
  Cc: Tim Harvey

Fix the dsa switch config:
- remove the unnecessary phy-mode from the switch itself
- added the necessary fixed-link node to the non-cpu ports required
  for U-Boot DSA

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 arch/arm/dts/imx8mm-venice-gw7901.dts | 37 ++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/arch/arm/dts/imx8mm-venice-gw7901.dts b/arch/arm/dts/imx8mm-venice-gw7901.dts
index 0216facb2a..124e1e4e70 100644
--- a/arch/arm/dts/imx8mm-venice-gw7901.dts
+++ b/arch/arm/dts/imx8mm-venice-gw7901.dts
@@ -577,7 +577,6 @@
 		pinctrl-0 = <&pinctrl_ksz>;
 		interrupt-parent = <&gpio4>;
 		interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
-		phy-mode = "rgmii-id";
 
 		ports {
 			#address-cells = <1>;
@@ -587,24 +586,32 @@
 				reg = <0>;
 				label = "lan1";
 				local-mac-address = [00 00 00 00 00 00];
+				phy-handle = <&sw_phy0>;
+				phy-mode = "internal";
 			};
 
 			lan2: port@1 {
 				reg = <1>;
 				label = "lan2";
 				local-mac-address = [00 00 00 00 00 00];
+				phy-handle = <&sw_phy1>;
+				phy-mode = "internal";
 			};
 
 			lan3: port@2 {
 				reg = <2>;
 				label = "lan3";
 				local-mac-address = [00 00 00 00 00 00];
+				phy-handle = <&sw_phy2>;
+				phy-mode = "internal";
 			};
 
 			lan4: port@3 {
 				reg = <3>;
 				label = "lan4";
 				local-mac-address = [00 00 00 00 00 00];
+				phy-handle = <&sw_phy3>;
+				phy-mode = "internal";
 			};
 
 			port@5 {
@@ -619,6 +626,34 @@
 				};
 			};
 		};
+
+		mdios {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			mdio@0 {
+				reg = <0>;
+				compatible = "microchip,ksz-mdio";
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				sw_phy0: ethernet-phy@0 {
+					reg = <0x0>;
+				};
+
+				sw_phy1: ethernet-phy@1 {
+					reg = <0x1>;
+				};
+
+				sw_phy2: ethernet-phy@2 {
+					reg = <0x2>;
+				};
+
+				sw_phy3: ethernet-phy@3 {
+					reg = <0x3>;
+				};
+			};
+		};
 	};
 
 	crypto@60 {
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* [PATCH 9/9] configs: imx8mm_venice_defconfig: add support for gbe switch
  2021-06-30 23:50 [PATCH 0/9] Add support for imx8mm-venice-gw7901 and DSA switch Tim Harvey
                   ` (7 preceding siblings ...)
  2021-06-30 23:50 ` [PATCH 8/9] arm: dts: imx8mm-venice-gw7901.dts: fix dsa switch configuration Tim Harvey
@ 2021-06-30 23:50 ` Tim Harvey
  2021-07-10 19:37   ` sbabic
  8 siblings, 1 reply; 25+ messages in thread
From: Tim Harvey @ 2021-06-30 23:50 UTC (permalink / raw)
  To: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, Ramon Fried, u-boot, Vladimir Oltean,
	Claudiu Manoil, Michael Walle
  Cc: Tim Harvey

The imx8mm-venice-gw7901 board has an I2C connected KSZ9897S GbE switch
with an IMX8MM FEC MAC master connected via RGMII_ID.

Signed-off-by: Tim Harvey <tharvey@gateworks.com>
---
 configs/imx8mm_venice_defconfig | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/configs/imx8mm_venice_defconfig b/configs/imx8mm_venice_defconfig
index 3961db00cb..49affccec4 100644
--- a/configs/imx8mm_venice_defconfig
+++ b/configs/imx8mm_venice_defconfig
@@ -87,9 +87,13 @@ CONFIG_SPL_MMC_HS400_SUPPORT=y
 CONFIG_FSL_USDHC=y
 CONFIG_PHYLIB=y
 CONFIG_PHY_TI_DP83867=y
+CONFIG_PHY_FIXED=y
 CONFIG_DM_ETH=y
+CONFIG_DM_MDIO=y
+CONFIG_DM_DSA=y
 CONFIG_PHY_GIGE=y
 CONFIG_FEC_MXC=y
+CONFIG_KSZ9477=y
 CONFIG_MII=y
 CONFIG_PINCTRL=y
 CONFIG_SPL_PINCTRL=y
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 25+ messages in thread

* Re: [PATCH 2/9] net: fec: use device sequence vs index when fetching fec
  2021-06-30 23:50 ` [PATCH 2/9] net: fec: use device sequence vs index when fetching fec Tim Harvey
@ 2021-07-02  9:44   ` Ramon Fried
  2021-07-10 19:35   ` sbabic
  1 sibling, 0 replies; 25+ messages in thread
From: Ramon Fried @ 2021-07-02  9:44 UTC (permalink / raw)
  To: Tim Harvey
  Cc: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, U-Boot Mailing List, Vladimir Oltean,
	Claudiu Manoil, Michael Walle

On Thu, Jul 1, 2021 at 2:50 AM Tim Harvey <tharvey@gateworks.com> wrote:
>
> When using uclass_get_device* to get the FEC device we need to use
> device sequence instead of index into UCLASS_ETH. In systems where for
> example a I2C based DSA switch exists it will probe before the FEC
> master and its ports will be registered first and have the first
> indexes yet the FEC's sequence comes from the device-tree alias.
>
> Take for example the imx8mm-venice-gw7901 board which has an i2c based
> DSA switch:
>
> u-boot=> net list
> eth1 : lan1 00:0d:8d:aa:00:2f
> eth2 : lan2 00:0d:8d:aa:00:30
> eth3 : lan3 00:0d:8d:aa:00:31
> eth4 : lan4 00:0d:8d:aa:00:32
> eth0 : ethernet@30be0000 00:0d:8d:aa:00:2e active
>
> Thus in this case uclass_get_device(UCLASS_ETH, 0, &dev) returns lan1
> which is wrong but uclass_get_device_seq(UCLASS_ETH, 0, &dev) returns
> ethernet@30be000 which is correct.
>
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> ---
>  drivers/net/fec_mxc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
> index 4fd5c01b4a..3abf914833 100644
> --- a/drivers/net/fec_mxc.c
> +++ b/drivers/net/fec_mxc.c
> @@ -146,7 +146,7 @@ static int fec_get_clk_rate(void *udev, int idx)
>             CONFIG_IS_ENABLED(CLK_CCF)) {
>                 dev = udev;
>                 if (!dev) {
> -                       ret = uclass_get_device(UCLASS_ETH, idx, &dev);
> +                       ret = uclass_get_device_by_seq(UCLASS_ETH, idx, &dev);
>                         if (ret < 0) {
>                                 debug("Can't get FEC udev: %d\n", ret);
>                                 return ret;
> --
> 2.17.1
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 3/9] net: fec: set phy_of_node properly for fixed-link phy
  2021-06-30 23:50 ` [PATCH 3/9] net: fec: set phy_of_node properly for fixed-link phy Tim Harvey
@ 2021-07-02  9:44   ` Ramon Fried
  2021-07-10 19:34   ` sbabic
  1 sibling, 0 replies; 25+ messages in thread
From: Ramon Fried @ 2021-07-02  9:44 UTC (permalink / raw)
  To: Tim Harvey
  Cc: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, U-Boot Mailing List, Vladimir Oltean,
	Claudiu Manoil, Michael Walle

On Thu, Jul 1, 2021 at 2:50 AM Tim Harvey <tharvey@gateworks.com> wrote:
>
> If the FEC is connected to a fixed-link (upstream switch port for
> example) the phy_of_node should be set to the fixed-link node
> so that speed and other properties can be found properly.
>
> In addition fix a typo in the debug string.
>
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> ---
>  drivers/net/fec_mxc.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
> index 3abf914833..77680491d0 100644
> --- a/drivers/net/fec_mxc.c
> +++ b/drivers/net/fec_mxc.c
> @@ -1304,7 +1304,11 @@ static int device_get_phy_addr(struct fec_priv *priv, struct udevice *dev)
>         ret = dev_read_phandle_with_args(dev, "phy-handle", NULL, 0, 0,
>                                          &phandle_args);
>         if (ret) {
> -               debug("Failed to find phy-handle (err = %d\n)", ret);
> +               priv->phy_of_node = ofnode_find_subnode(dev_ofnode(dev),
> +                                                       "fixed-link");
> +               if (ofnode_valid(priv->phy_of_node))
> +                       return 0;
> +               debug("Failed to find phy-handle (err = %d)\n", ret);
>                 return ret;
>         }
>
> --
> 2.17.1
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 4/9] net: add set_promisc function to enable/disable Promiscuous mode
  2021-06-30 23:50 ` [PATCH 4/9] net: add set_promisc function to enable/disable Promiscuous mode Tim Harvey
@ 2021-07-02  9:46   ` Ramon Fried
  2021-07-10 19:36   ` sbabic
  1 sibling, 0 replies; 25+ messages in thread
From: Ramon Fried @ 2021-07-02  9:46 UTC (permalink / raw)
  To: Tim Harvey
  Cc: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, U-Boot Mailing List, Vladimir Oltean,
	Claudiu Manoil, Michael Walle

On Thu, Jul 1, 2021 at 2:50 AM Tim Harvey <tharvey@gateworks.com> wrote:
>
> Enabling promiscuous mode can be useful for DSA switches where each port
> has its own MAC address.
>
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> ---
>  include/net.h | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/include/net.h b/include/net.h
> index b95d6a6f60..cec8c98618 100644
> --- a/include/net.h
> +++ b/include/net.h
> @@ -158,6 +158,7 @@ enum eth_recv_flags {
>   *                 ROM on the board. This is how the driver should expose it
>   *                 to the network stack. This function should fill in the
>   *                 eth_pdata::enetaddr field - optional
> + * set_promisc: Enable or Disable promiscuous mode
>   */
>  struct eth_ops {
>         int (*start)(struct udevice *dev);
> @@ -168,6 +169,7 @@ struct eth_ops {
>         int (*mcast)(struct udevice *dev, const u8 *enetaddr, int join);
>         int (*write_hwaddr)(struct udevice *dev);
>         int (*read_rom_hwaddr)(struct udevice *dev);
> +       int (*set_promisc)(struct udevice *dev, bool enable);
>  };
>
>  #define eth_get_ops(dev) ((struct eth_ops *)(dev)->driver->ops)
> --
> 2.17.1
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 5/9] net: fec: add set_promisc function
  2021-06-30 23:50 ` [PATCH 5/9] net: fec: add set_promisc function Tim Harvey
@ 2021-07-02  9:46   ` Ramon Fried
  2021-07-10 19:35   ` sbabic
  1 sibling, 0 replies; 25+ messages in thread
From: Ramon Fried @ 2021-07-02  9:46 UTC (permalink / raw)
  To: Tim Harvey
  Cc: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, U-Boot Mailing List, Vladimir Oltean,
	Claudiu Manoil, Michael Walle

On Thu, Jul 1, 2021 at 2:50 AM Tim Harvey <tharvey@gateworks.com> wrote:
>
> Enabling promiscuous mode is necessary if FEC is the master of a DSA
> switch driver where each port has their own MAC address.
>
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> ---
>  drivers/net/fec_mxc.c | 13 +++++++++++++
>  drivers/net/fec_mxc.h |  1 +
>  2 files changed, 14 insertions(+)
>
> diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c
> index 77680491d0..db2cdaf684 100644
> --- a/drivers/net/fec_mxc.c
> +++ b/drivers/net/fec_mxc.c
> @@ -458,6 +458,9 @@ static void fec_reg_setup(struct fec_priv *fec)
>         else if (fec->xcv_type == RMII)
>                 rcntrl |= FEC_RCNTRL_RMII;
>
> +       if (fec->promisc)
> +               rcntrl |= 0x8;
> +
>         writel(rcntrl, &fec->eth->r_cntrl);
>  }
>
> @@ -1278,6 +1281,15 @@ static int fecmxc_read_rom_hwaddr(struct udevice *dev)
>         return fec_get_hwaddr(priv->dev_id, pdata->enetaddr);
>  }
>
> +static int fecmxc_set_promisc(struct udevice *dev, bool enable)
> +{
> +       struct fec_priv *priv = dev_get_priv(dev);
> +
> +       priv->promisc = enable;
> +
> +       return 0;
> +}
> +
>  static int fecmxc_free_pkt(struct udevice *dev, uchar *packet, int length)
>  {
>         if (packet)
> @@ -1294,6 +1306,7 @@ static const struct eth_ops fecmxc_ops = {
>         .stop                   = fecmxc_halt,
>         .write_hwaddr           = fecmxc_set_hwaddr,
>         .read_rom_hwaddr        = fecmxc_read_rom_hwaddr,
> +       .set_promisc            = fecmxc_set_promisc,
>  };
>
>  static int device_get_phy_addr(struct fec_priv *priv, struct udevice *dev)
> diff --git a/drivers/net/fec_mxc.h b/drivers/net/fec_mxc.h
> index 5ccde9193b..62b55ef395 100644
> --- a/drivers/net/fec_mxc.h
> +++ b/drivers/net/fec_mxc.h
> @@ -272,6 +272,7 @@ struct fec_priv {
>         struct clk clk_ref;
>         struct clk clk_ptp;
>         u32 clk_rate;
> +       char promisc;
>  };
>
>  /**
> --
> 2.17.1
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 6/9] net: dsa: enable master promisc mode if available and needed
  2021-06-30 23:50 ` [PATCH 6/9] net: dsa: enable master promisc mode if available and needed Tim Harvey
@ 2021-07-02  9:47   ` Ramon Fried
  2021-07-10 19:35   ` sbabic
  1 sibling, 0 replies; 25+ messages in thread
From: Ramon Fried @ 2021-07-02  9:47 UTC (permalink / raw)
  To: Tim Harvey
  Cc: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, U-Boot Mailing List, Vladimir Oltean,
	Claudiu Manoil, Michael Walle

On Thu, Jul 1, 2021 at 2:50 AM Tim Harvey <tharvey@gateworks.com> wrote:
>
> If ports have their own unique MAC addrs and master has a set_promisc
> function, call it so that packets will be received for ports.
>
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> ---
>  net/dsa-uclass.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c
> index 7ea1cb6949..694664d81b 100644
> --- a/net/dsa-uclass.c
> +++ b/net/dsa-uclass.c
> @@ -277,8 +277,15 @@ static int dsa_port_probe(struct udevice *pdev)
>          * has a unique MAC address specified in the environment.
>          */
>         eth_env_get_enetaddr_by_index("eth", dev_seq(pdev), env_enetaddr);
> -       if (!is_zero_ethaddr(env_enetaddr))
> +       if (!is_zero_ethaddr(env_enetaddr)) {
> +               /* individual port mac addrs require master to be promisc */
> +               struct eth_ops *eth_ops = eth_get_ops(master);
> +
> +               if (eth_ops->set_promisc)
> +                       eth_ops->set_promisc(master, 1);
> +
>                 return 0;
> +       }
>
>         master_pdata = dev_get_plat(master);
>         eth_pdata = dev_get_plat(pdev);
> --
> 2.17.1
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* Re: [PATCH 7/9] net: add support for KSZ9477/KSZ9897/KSZ9567 GbE switch
  2021-06-30 23:50 ` [PATCH 7/9] net: add support for KSZ9477/KSZ9897/KSZ9567 GbE switch Tim Harvey
@ 2021-07-02  9:49   ` Ramon Fried
  2021-07-10 19:35   ` sbabic
  1 sibling, 0 replies; 25+ messages in thread
From: Ramon Fried @ 2021-07-02  9:49 UTC (permalink / raw)
  To: Tim Harvey
  Cc: Stefano Babic, Fabio Estevam, NXP i . MX U-Boot Team,
	Joe Hershberger, U-Boot Mailing List, Vladimir Oltean,
	Claudiu Manoil, Michael Walle

On Thu, Jul 1, 2021 at 2:50 AM Tim Harvey <tharvey@gateworks.com> wrote:
>
> The Microchip KSZ9477/KSZ9897/KSZ9567 7-Port Gigabit Ethernet Switches
> support SGMII/RGMII/MII/RMII with register access via SPI, I2C, or MDIO.
>
> This driver currently supports I2C register access but SPI or MDIO register
> access can be easily added at a later time.
>
> Tagging is not implemented and instead the active port is tracked to
> avoid needing a tag to store port information.
>
> This was tested with the imx8mm-venice-gw7901 board which has a
> KSZ9897S switch with an IMX8MM FEC MAC master connected via RGMII_ID.
>
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> ---
>  drivers/net/Kconfig   |   7 +
>  drivers/net/Makefile  |   1 +
>  drivers/net/ksz9477.c | 547 ++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 555 insertions(+)
>  create mode 100644 drivers/net/ksz9477.c
>
> diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
> index 9fc28b149d..feeea960e2 100644
> --- a/drivers/net/Kconfig
> +++ b/drivers/net/Kconfig
> @@ -402,6 +402,13 @@ config KS8851_MLL_BASEADDR
>  endif #DM_ETH
>  endif #KS8851_MLL
>
> +config KSZ9477
> +       bool "Microchip KSZ9477 I2C controller driver"
> +       depends on DM_DSA && DM_I2C
> +       help
> +         This driver implements a DSA switch driver for the KSZ9477 family
> +         of GbE switches using the I2C interface.
> +
>  config MVGBE
>         bool "Marvell Orion5x/Kirkwood network interface support"
>         depends on ARCH_KIRKWOOD || ARCH_ORION5X
> diff --git a/drivers/net/Makefile b/drivers/net/Makefile
> index d56baa65b2..03900ffa3a 100644
> --- a/drivers/net/Makefile
> +++ b/drivers/net/Makefile
> @@ -39,6 +39,7 @@ obj-$(CONFIG_FTMAC110) += ftmac110.o
>  obj-$(CONFIG_FTMAC100) += ftmac100.o
>  obj-$(CONFIG_GMAC_ROCKCHIP) += gmac_rockchip.o
>  obj-$(CONFIG_KS8851_MLL) += ks8851_mll.o
> +obj-$(CONFIG_KSZ9477) += ksz9477.o
>  obj-$(CONFIG_LAN91C96) += lan91c96.o
>  obj-$(CONFIG_LPC32XX_ETH) += lpc32xx_eth.o
>  obj-$(CONFIG_MACB) += macb.o
> diff --git a/drivers/net/ksz9477.c b/drivers/net/ksz9477.c
> new file mode 100644
> index 0000000000..ab32f42127
> --- /dev/null
> +++ b/drivers/net/ksz9477.c
> @@ -0,0 +1,547 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * (C) Copyright 2020
> + * Tim Harvey, Gateworks Corporation
> + */
> +
> +#include <dm.h>
> +#include <dm/device_compat.h>
> +#include <dm/device-internal.h>
> +#include <dm/lists.h>
> +#include <eth_phy.h>
> +#include <linux/delay.h>
> +#include <miiphy.h>
> +#include <i2c.h>
> +#include <net/dsa.h>
> +
> +#include <asm-generic/gpio.h>
> +
> +/* Global registers */
> +
> +/* Chip ID */
> +#define REG_CHIP_ID0__1                        0x0000
> +
> +/* Operation control */
> +#define REG_SW_OPERATION               0x0300
> +#define SW_RESET                       BIT(1)
> +#define SW_START                       BIT(0)
> +
> +/* Port Specific Registers */
> +#define PORT_CTRL_ADDR(port, addr) ((addr) | (((port) + 1) << 12))
> +
> +/* Port Control */
> +#define REG_PORT_XMII_CTRL_1           0x0301
> +#define PORT_MII_NOT_1GBIT             BIT(6)
> +#define PORT_MII_SEL_EDGE              BIT(5)
> +#define PORT_RGMII_ID_IG_ENABLE                BIT(4)
> +#define PORT_RGMII_ID_EG_ENABLE                BIT(3)
> +#define PORT_MII_MAC_MODE              BIT(2)
> +#define PORT_MII_SEL_M                 0x3
> +#define PORT_RGMII_SEL                 0x0
> +#define PORT_RMII_SEL                  0x1
> +#define PORT_GMII_SEL                  0x2
> +#define PORT_MII_SEL                   0x3
> +
> +/* Port MSTP State Register */
> +#define REG_PORT_MSTP_STATE            0x0b04
> +#define PORT_TX_ENABLE                 BIT(2)
> +#define PORT_RX_ENABLE                 BIT(1)
> +#define PORT_LEARN_DISABLE             BIT(0)
> +
> +/* MMD */
> +#define REG_PORT_PHY_MMD_SETUP         0x011A
> +#define PORT_MMD_OP_MODE_M             0x3
> +#define PORT_MMD_OP_MODE_S             14
> +#define PORT_MMD_OP_INDEX              0
> +#define PORT_MMD_OP_DATA_NO_INCR       1
> +#define PORT_MMD_OP_DATA_INCR_RW       2
> +#define PORT_MMD_OP_DATA_INCR_W                3
> +#define PORT_MMD_DEVICE_ID_M           0x1F
> +#define MMD_SETUP(mode, dev)           (((u16)(mode) << PORT_MMD_OP_MODE_S) | (dev))
> +#define REG_PORT_PHY_MMD_INDEX_DATA    0x011C
> +
> +struct ksz_dsa_priv {
> +       struct udevice *dev;
> +       int active_port;
> +};
> +
> +static inline int ksz_read8(struct udevice *dev, u32 reg, u8 *val)
> +{
> +       int ret = dm_i2c_read(dev, reg, val, 1);
> +
> +       dev_dbg(dev, "%s 0x%04x<<0x%02x\n", __func__, reg, *val);
> +
> +       return ret;
> +}
> +
> +static inline int ksz_pread8(struct udevice *dev, int port, int reg, u8 *val)
> +{
> +       return ksz_read8(dev, PORT_CTRL_ADDR(port, reg), val);
> +}
> +
> +static inline int ksz_write8(struct udevice *dev, u32 reg, u8 val)
> +{
> +       dev_dbg(dev, "%s 0x%04x>>0x%02x\n", __func__, reg, val);
> +       return dm_i2c_write(dev, reg, &val, 1);
> +}
> +
> +static inline int ksz_pwrite8(struct udevice *dev, int port, int reg, u8 val)
> +{
> +       return ksz_write8(dev, PORT_CTRL_ADDR(port, reg), val);
> +}
> +
> +static inline int ksz_write16(struct udevice *dev, u32 reg, u16 val)
> +{
> +       u8 buf[2];
> +
> +       buf[1] = val & 0xff;
> +       buf[0] = val >> 8;
> +       dev_dbg(dev, "%s 0x%04x>>0x%04x\n", __func__, reg, val);
> +
> +       return dm_i2c_write(dev, reg, buf, 2);
> +}
> +
> +static inline int ksz_pwrite16(struct udevice *dev, int port, int reg, u16 val)
> +{
> +       return ksz_write16(dev, PORT_CTRL_ADDR(port, reg), val);
> +}
> +
> +static inline int ksz_read16(struct udevice *dev, u32 reg, u16 *val)
> +{
> +       u8 buf[2];
> +       int ret;
> +
> +       ret = dm_i2c_read(dev, reg, buf, 2);
> +       *val = (buf[0] << 8) | buf[1];
> +       dev_dbg(dev, "%s 0x%04x<<0x%04x\n", __func__, reg, *val);
> +
> +       return ret;
> +}
> +
> +static inline int ksz_pread16(struct udevice *dev, int port, int reg, u16 *val)
> +{
> +       return ksz_read16(dev, PORT_CTRL_ADDR(port, reg), val);
> +}
> +
> +static inline int ksz_read32(struct udevice *dev, u32 reg, u32 *val)
> +{
> +       return dm_i2c_read(dev, reg, (u8 *)val, 4);
> +}
> +
> +static inline int ksz_pread32(struct udevice *dev, int port, int reg, u32 *val)
> +{
> +       return ksz_read32(dev, PORT_CTRL_ADDR(port, reg), val);
> +}
> +
> +static inline int ksz_write32(struct udevice *dev, u32 reg, u32 val)
> +{
> +       u8 buf[4];
> +
> +       buf[3] = val & 0xff;
> +       buf[2] = (val >> 24) & 0xff;
> +       buf[1] = (val >> 16) & 0xff;
> +       buf[0] = (val >> 8) & 0xff;
> +       dev_dbg(dev, "%s 0x%04x>>0x%04x\n", __func__, reg, val);
> +
> +       return dm_i2c_write(dev, reg, buf, 4);
> +}
> +
> +static inline int ksz_pwrite32(struct udevice *dev, int port, int reg, u32 val)
> +{
> +       return ksz_write32(dev, PORT_CTRL_ADDR(port, reg), val);
> +}
> +
> +static __maybe_unused void ksz_port_mmd_read(struct udevice *dev, int port,
> +                                            u8 addr, u16 reg, u16 *val)
> +{
> +       ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_INDEX, addr));
> +       ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, reg);
> +       ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, addr));
> +       ksz_pread16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
> +       dev_dbg(dev, "%s  P%d 0x%02x:0x%04x<<0x%04x\n", __func__, port + 1, addr, reg, *val);
> +}
> +
> +static void ksz_port_mmd_write(struct udevice *dev, int port, u8 addr, u16 reg, u16 val)
> +{
> +       dev_dbg(dev, "%s P%d 0x%02x:0x%04x>>0x%04x\n", __func__, port + 1, addr, addr, val);
> +       ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_INDEX, addr));
> +       ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, addr);
> +       ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, addr));
> +       ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val);
> +}
> +
> +/* Apply PHY settings to address errata listed in KSZ9477, KSZ9897, KSZ9896, KSZ9567
> + * Silicon Errata and Data Sheet Clarification documents
> + */
> +static void ksz_phy_errata_setup(struct udevice *dev, int port)
> +{
> +       dev_dbg(dev, "%s P%d\n", __func__, port + 1);
> +
> +       /* Register settings are needed to improve PHY receive performance */
> +       ksz_port_mmd_write(dev, port, 0x01, 0x6f, 0xdd0b);
> +       ksz_port_mmd_write(dev, port, 0x01, 0x8f, 0x6032);
> +       ksz_port_mmd_write(dev, port, 0x01, 0x9d, 0x248c);
> +       ksz_port_mmd_write(dev, port, 0x01, 0x75, 0x0060);
> +       ksz_port_mmd_write(dev, port, 0x01, 0xd3, 0x7777);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x06, 0x3008);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x08, 0x2001);
> +
> +       /* Transmit waveform amplitude can be improved (1000BASE-T, 100BASE-TX, 10BASE-Te) */
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x04, 0x00d0);
> +
> +       /* Energy Efficient Ethernet (EEE) feature select must be manually disabled */
> +       ksz_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000);
> +
> +       /* Register settings are required to meet data sheet supply current specifications */
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x13, 0x6eff);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x14, 0xe6ff);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x15, 0x6eff);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x16, 0xe6ff);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x17, 0x00ff);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x18, 0x43ff);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x19, 0xc3ff);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x1a, 0x6fff);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x1b, 0x07ff);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x1c, 0x0fff);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x1d, 0xe7ff);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x1e, 0xefff);
> +       ksz_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee);
> +}
> +
> +/*
> + * mii bus driver
> + */
> +#define KSZ_MDIO_CHILD_DRV_NAME        "ksz_mdio"
> +
> +struct ksz_mdio_priv {
> +       struct ksz_dsa_priv *ksz;
> +};
> +
> +static int dm_ksz_mdio_read(struct udevice *dev, int addr, int devad, int reg)
> +{
> +       struct ksz_mdio_priv *priv = dev_get_priv(dev);
> +       struct ksz_dsa_priv *ksz = priv->ksz;
> +       u16 val = 0xffff;
> +
> +       ksz_pread16(ksz->dev, addr, 0x100 + (reg << 1), &val);
> +       dev_dbg(ksz->dev, "%s P%d reg=0x%04x:0x%04x<<0x%04x\n", __func__,
> +               addr + 1, reg, 0x100 + (reg << 1), val);
> +
> +       return val;
> +};
> +
> +static int dm_ksz_mdio_write(struct udevice *dev, int addr, int devad, int reg, u16 val)
> +{
> +       struct ksz_mdio_priv *priv = dev_get_priv(dev);
> +       struct ksz_dsa_priv *ksz = priv->ksz;
> +
> +       dev_dbg(ksz->dev, "%s P%d reg=0x%04x:%04x>>0x%04x\n",
> +               __func__, addr + 1, reg, 0x100 + (reg << 1), val);
> +       ksz_pwrite16(ksz->dev, addr, 0x100 + (reg << 1), val);
> +
> +       return 0;
> +}
> +
> +static const struct mdio_ops ksz_mdio_ops = {
> +       .read = dm_ksz_mdio_read,
> +       .write = dm_ksz_mdio_write,
> +};
> +
> +static int ksz_mdio_bind(struct udevice *dev)
> +{
> +       char name[16];
> +       static int num_devices;
> +
> +       dev_dbg(dev, "%s\n", __func__);
> +       sprintf(name, "ksz-mdio-%d", num_devices++);
> +       device_set_name(dev, name);
> +
> +       return 0;
> +}
> +
> +static int ksz_mdio_probe(struct udevice *dev)
> +{
> +       struct ksz_mdio_priv *priv = dev_get_priv(dev);
> +
> +       dev_dbg(dev, "%s\n", __func__);
> +       priv->ksz = dev_get_parent_priv(dev->parent);
> +
> +       return 0;
> +}
> +
> +static const struct udevice_id ksz_mdio_ids[] = {
> +       { .compatible = "microchip,ksz-mdio" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(ksz_mdio) = {
> +       .name           = KSZ_MDIO_CHILD_DRV_NAME,
> +       .id             = UCLASS_MDIO,
> +       .of_match       = ksz_mdio_ids,
> +       .bind           = ksz_mdio_bind,
> +       .probe          = ksz_mdio_probe,
> +       .ops            = &ksz_mdio_ops,
> +       .priv_auto      = sizeof(struct ksz_mdio_priv),
> +       .plat_auto      = sizeof(struct mdio_perdev_priv),
> +};
> +
> +static int ksz_port_setup(struct udevice *dev, int port,
> +                         phy_interface_t interface)
> +{
> +       struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
> +       u8 data8;
> +
> +       dev_dbg(dev, "%s P%d %s\n", __func__, port + 1,
> +               (port == pdata->cpu_port) ? "cpu" : "");
> +
> +       if (port != pdata->cpu_port) {
> +               /* phy port: config errata and leds */
> +               ksz_phy_errata_setup(dev, port);
> +       } else {
> +               /* cpu port: configure MAC interface mode */
> +               ksz_pread8(dev, port, REG_PORT_XMII_CTRL_1, &data8);
> +               dev_dbg(dev, "%s P%d cpu interface %s\n", __func__, port + 1,
> +                       phy_string_for_interface(interface));
> +               switch (interface) {
> +               case PHY_INTERFACE_MODE_MII:
> +                       data8 &= ~PORT_MII_SEL_M;
> +                       data8 |= PORT_MII_SEL;
> +                       data8 |= PORT_MII_NOT_1GBIT;
> +                       break;
> +               case PHY_INTERFACE_MODE_RMII:
> +                       data8 &= ~PORT_MII_SEL_M;
> +                       data8 |= PORT_RMII_SEL;
> +                       data8 |= PORT_MII_NOT_1GBIT;
> +                       break;
> +               case PHY_INTERFACE_MODE_GMII:
> +                       data8 &= ~PORT_MII_SEL_M;
> +                       data8 |= PORT_GMII_SEL;
> +                       data8 &= ~PORT_MII_NOT_1GBIT;
> +                       break;
> +               default:
> +                       data8 &= ~PORT_MII_SEL_M;
> +                       data8 |= PORT_RGMII_SEL;
> +                       data8 &= ~PORT_MII_NOT_1GBIT;
> +                       data8 &= ~PORT_RGMII_ID_IG_ENABLE;
> +                       data8 &= ~PORT_RGMII_ID_EG_ENABLE;
> +                       if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
> +                           interface == PHY_INTERFACE_MODE_RGMII_RXID)
> +                               data8 |= PORT_RGMII_ID_IG_ENABLE;
> +                       if (interface == PHY_INTERFACE_MODE_RGMII_ID ||
> +                           interface == PHY_INTERFACE_MODE_RGMII_TXID)
> +                               data8 |= PORT_RGMII_ID_EG_ENABLE;
> +                       break;
> +               }
> +               ksz_write8(dev, PORT_CTRL_ADDR(port, REG_PORT_XMII_CTRL_1), data8);
> +       }
> +
> +       return 0;
> +}
> +
> +static int ksz_port_enable(struct udevice *dev, int port, struct phy_device *phy)
> +{
> +       struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
> +       struct ksz_dsa_priv *priv = dev_get_priv(dev);
> +       int supported = PHY_GBIT_FEATURES;
> +       u8 data8;
> +       int ret;
> +
> +       dev_dbg(dev, "%s P%d 0x%x %s\n", __func__, port + 1, phy->phy_id,
> +               phy_string_for_interface(phy->interface));
> +
> +       /* setup this port */
> +       ret = ksz_port_setup(dev, port, phy->interface);
> +       if (ret) {
> +               dev_err(dev, "port setup failed: %d\n", ret);
> +               return ret;
> +       }
> +
> +       /* enable port forwarding for this port */
> +       ksz_pread8(priv->dev, port, REG_PORT_MSTP_STATE, &data8);
> +       data8 &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
> +       data8 |= (PORT_TX_ENABLE | PORT_RX_ENABLE);
> +       ksz_pwrite8(priv->dev, port, REG_PORT_MSTP_STATE, data8);
> +
> +       /* if cpu master we are done */
> +       if (port == pdata->cpu_port)
> +               return 0;
> +
> +       /* configure phy */
> +       phy->supported &= supported;
> +       phy->advertising &= supported;
> +       ret = phy_config(phy);
> +       if (ret)
> +               return ret;
> +
> +       ret = phy_startup(phy);
> +       if (ret)
> +               return ret;
> +
> +       /* start switch */
> +       ksz_read8(priv->dev, REG_SW_OPERATION, &data8);
> +       data8 |= SW_START;
> +       ksz_write8(priv->dev, REG_SW_OPERATION, data8);
> +
> +       /* keep track of current enabled non-cpu port */
> +       priv->active_port = port;
> +
> +       return 0;
> +}
> +
> +static void ksz_port_disable(struct udevice *dev, int port, struct phy_device *phy)
> +{
> +       struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
> +       struct ksz_dsa_priv *priv = dev_get_priv(dev);
> +       u8 data8;
> +
> +       dev_dbg(dev, "%s P%d 0x%x\n", __func__, port + 1, phy->phy_id);
> +
> +       /* can't disable CPU port without re-configuring/re-starting switch */
> +       if (port == pdata->cpu_port)
> +               return;
> +
> +       /* disable port */
> +       ksz_pread8(priv->dev, port, REG_PORT_MSTP_STATE, &data8);
> +       data8 &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
> +       data8 |= PORT_LEARN_DISABLE;
> +       ksz_pwrite8(priv->dev, port, REG_PORT_MSTP_STATE, data8);
> +
> +       /*
> +        * we don't call phy_shutdown here to avoid waiting next time we use
> +        * the port, but the downside is that remote side will think we're
> +        * actively processing traffic although we are not.
> +        */
> +}
> +
> +static int ksz_xmit(struct udevice *dev, int port, void *packet, int length)
> +{
> +       dev_dbg(dev, "%s P%d %d\n", __func__, port + 1, length);
> +
> +       return 0;
> +}
> +
> +static int ksz_recv(struct udevice *dev, int *port, void *packet, int length)
> +{
> +       struct ksz_dsa_priv *priv = dev_get_priv(dev);
> +
> +       dev_dbg(dev, "%s P%d %d\n", __func__, priv->active_port + 1, length);
> +       *port = priv->active_port;
> +
> +       return 0;
> +};
> +
> +static const struct dsa_ops ksz_dsa_ops = {
> +       .port_enable = ksz_port_enable,
> +       .port_disable = ksz_port_disable,
> +       .xmit = ksz_xmit,
> +       .rcv = ksz_recv,
> +};
> +
> +static int ksz_probe_mdio(struct udevice *dev)
> +{
> +       ofnode node, mdios;
> +       int ret;
> +
> +       mdios = dev_read_subnode(dev, "mdios");
> +       if (ofnode_valid(mdios)) {
> +               ofnode_for_each_subnode(node, mdios) {
> +                       const char *name = ofnode_get_name(node);
> +                       struct udevice *pdev;
> +
> +                       ret = device_bind_driver_to_node(dev,
> +                                                        KSZ_MDIO_CHILD_DRV_NAME,
> +                                                        name, node, &pdev);
> +                       if (ret)
> +                               dev_err(dev, "failed to probe %s: %d\n", name, ret);
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +/*
> + * I2C driver
> + */
> +static int ksz_i2c_probe(struct udevice *dev)
> +{
> +       struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
> +       struct ksz_dsa_priv *priv = dev_get_priv(dev);
> +       struct udevice *master = dsa_get_master(dev);
> +       int i, ret;
> +       u8 data8;
> +       u32 id;
> +
> +       if (!master)
> +               return -ENODEV;
> +
> +       dev_dbg(dev, "%s %s master:%s\n", __func__, dev->name, master->name);
> +       dev_set_parent_priv(dev, priv);
> +
> +       ret = i2c_set_chip_offset_len(dev, 2);
> +       if (ret) {
> +               printf("i2c_set_chip_offset_len failed: %d\n", ret);
> +               return ret;
> +       }
> +
> +       /* default config */
> +       priv->dev = dev;
> +
> +       /* chip level reset */
> +       ksz_read8(priv->dev, REG_SW_OPERATION, &data8);
> +       data8 |= SW_RESET;
> +       ksz_write8(priv->dev, REG_SW_OPERATION, data8);
> +
> +       /* read chip id */
> +       ret = ksz_read32(dev, REG_CHIP_ID0__1, &id);
> +       if (ret)
> +               return ret;
> +       id = __swab32(id);
> +       dev_dbg(dev, "%s id=0x%08x\n", __func__, id);
> +       switch (id & 0xffffff00) {
> +       case 0x00947700:
> +               puts("KSZ9477S: ");
> +               break;
> +       case 0x00956700:
> +               puts("KSZ9567R: ");
> +               break;
> +       case 0x00989700:
> +               puts("KSZ9897S: ");
> +               break;
> +       default:
> +               dev_err(dev, "invalid chip id: 0x%08x\n", id);
> +               return -EINVAL;
> +       }
> +
> +       /* probe mdio bus */
> +       ret = ksz_probe_mdio(dev);
> +       if (ret)
> +               return ret;
> +
> +       /* disable ports by default */
> +       for (i = 0; i < pdata->num_ports; i++) {
> +               ksz_pread8(priv->dev, i, REG_PORT_MSTP_STATE, &data8);
> +               data8 &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
> +               ksz_pwrite8(priv->dev, i, REG_PORT_MSTP_STATE, data8);
> +       }
> +
> +       dsa_set_tagging(dev, 0, 0);
> +
> +       return 0;
> +};
> +
> +static const struct udevice_id ksz_i2c_ids[] = {
> +       { .compatible = "microchip,ksz9897" },
> +       { .compatible = "microchip,ksz9477" },
> +       { .compatible = "microchip,ksz9567" },
> +       { }
> +};
> +
> +U_BOOT_DRIVER(ksz) = {
> +       .name           = "ksz-switch",
> +       .id             = UCLASS_DSA,
> +       .of_match       = ksz_i2c_ids,
> +       .probe          = ksz_i2c_probe,
> +       .ops            = &ksz_dsa_ops,
> +       .priv_auto      = sizeof(struct ksz_dsa_priv),
> +};
> +
> --
> 2.17.1
>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 3/9] net: fec: set phy_of_node properly for fixed-link phy
  2021-06-30 23:50 ` [PATCH 3/9] net: fec: set phy_of_node properly for fixed-link phy Tim Harvey
  2021-07-02  9:44   ` Ramon Fried
@ 2021-07-10 19:34   ` sbabic
  1 sibling, 0 replies; 25+ messages in thread
From: sbabic @ 2021-07-10 19:34 UTC (permalink / raw)
  To: Tim Harvey, u-boot

> If the FEC is connected to a fixed-link (upstream switch port for
> example) the phy_of_node should be set to the fixed-link node
> so that speed and other properties can be found properly.
> In addition fix a typo in the debug string.
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 5/9] net: fec: add set_promisc function
  2021-06-30 23:50 ` [PATCH 5/9] net: fec: add set_promisc function Tim Harvey
  2021-07-02  9:46   ` Ramon Fried
@ 2021-07-10 19:35   ` sbabic
  1 sibling, 0 replies; 25+ messages in thread
From: sbabic @ 2021-07-10 19:35 UTC (permalink / raw)
  To: Tim Harvey, u-boot

> Enabling promiscuous mode is necessary if FEC is the master of a DSA
> switch driver where each port has their own MAC address.
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 8/9] arm: dts: imx8mm-venice-gw7901.dts: fix dsa switch configuration
  2021-06-30 23:50 ` [PATCH 8/9] arm: dts: imx8mm-venice-gw7901.dts: fix dsa switch configuration Tim Harvey
@ 2021-07-10 19:35   ` sbabic
  0 siblings, 0 replies; 25+ messages in thread
From: sbabic @ 2021-07-10 19:35 UTC (permalink / raw)
  To: Tim Harvey, u-boot

> Fix the dsa switch config:
> - remove the unnecessary phy-mode from the switch itself
> - added the necessary fixed-link node to the non-cpu ports required
>   for U-Boot DSA
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 1/9] board: gateworks: venice: add imx8mm-gw7901 support
  2021-06-30 23:50 ` [PATCH 1/9] board: gateworks: venice: add imx8mm-gw7901 support Tim Harvey
@ 2021-07-10 19:35   ` sbabic
  0 siblings, 0 replies; 25+ messages in thread
From: sbabic @ 2021-07-10 19:35 UTC (permalink / raw)
  To: Tim Harvey, u-boot

> The Gateworks GW7901 is an ARM based single board computer (SBC)
> featuring:
>  - i.MX8M Mini SoC
>  - LPDDR4 DRAM
>  - eMMC FLASH
>  - SPI FRAM
>  - Gateworks System Controller (GSC)
>  - Atmel ATECC Crypto Authentication
>  - USB 2.0
>  - Microchip GbE Switch
>  - Multiple multi-protocol RS232/RS485/RS422 Serial ports
>  - onboard 802.11ac WiFi / BT
>  - microSD socket
>  - miniPCIe socket with PCIe, USB 2.0 and dual SIM sockets
>  - Wide range DC power input
>  - 802.3at PoE
> To add support for this board:
>  - add dts from Linux (accepted for v5.14)
>  - add SPL PMIC config
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 2/9] net: fec: use device sequence vs index when fetching fec
  2021-06-30 23:50 ` [PATCH 2/9] net: fec: use device sequence vs index when fetching fec Tim Harvey
  2021-07-02  9:44   ` Ramon Fried
@ 2021-07-10 19:35   ` sbabic
  1 sibling, 0 replies; 25+ messages in thread
From: sbabic @ 2021-07-10 19:35 UTC (permalink / raw)
  To: Tim Harvey, u-boot

> When using uclass_get_device* to get the FEC device we need to use
> device sequence instead of index into UCLASS_ETH. In systems where for
> example a I2C based DSA switch exists it will probe before the FEC
> master and its ports will be registered first and have the first
> indexes yet the FEC's sequence comes from the device-tree alias.
> Take for example the imx8mm-venice-gw7901 board which has an i2c based
> DSA switch:
> u-boot=> net list
> eth1 : lan1 00:0d:8d:aa:00:2f
> eth2 : lan2 00:0d:8d:aa:00:30
> eth3 : lan3 00:0d:8d:aa:00:31
> eth4 : lan4 00:0d:8d:aa:00:32
> eth0 : ethernet@30be0000 00:0d:8d:aa:00:2e active
> Thus in this case uclass_get_device(UCLASS_ETH, 0, &dev) returns lan1
> which is wrong but uclass_get_device_seq(UCLASS_ETH, 0, &dev) returns
> ethernet@30be000 which is correct.
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 6/9] net: dsa: enable master promisc mode if available and needed
  2021-06-30 23:50 ` [PATCH 6/9] net: dsa: enable master promisc mode if available and needed Tim Harvey
  2021-07-02  9:47   ` Ramon Fried
@ 2021-07-10 19:35   ` sbabic
  1 sibling, 0 replies; 25+ messages in thread
From: sbabic @ 2021-07-10 19:35 UTC (permalink / raw)
  To: Tim Harvey, u-boot

> If ports have their own unique MAC addrs and master has a set_promisc
> function, call it so that packets will be received for ports.
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 7/9] net: add support for KSZ9477/KSZ9897/KSZ9567 GbE switch
  2021-06-30 23:50 ` [PATCH 7/9] net: add support for KSZ9477/KSZ9897/KSZ9567 GbE switch Tim Harvey
  2021-07-02  9:49   ` Ramon Fried
@ 2021-07-10 19:35   ` sbabic
  1 sibling, 0 replies; 25+ messages in thread
From: sbabic @ 2021-07-10 19:35 UTC (permalink / raw)
  To: Tim Harvey, u-boot

> The Microchip KSZ9477/KSZ9897/KSZ9567 7-Port Gigabit Ethernet Switches
> support SGMII/RGMII/MII/RMII with register access via SPI, I2C, or MDIO.
> This driver currently supports I2C register access but SPI or MDIO register
> access can be easily added at a later time.
> Tagging is not implemented and instead the active port is tracked to
> avoid needing a tag to store port information.
> This was tested with the imx8mm-venice-gw7901 board which has a
> KSZ9897S switch with an IMX8MM FEC MAC master connected via RGMII_ID.
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 4/9] net: add set_promisc function to enable/disable Promiscuous mode
  2021-06-30 23:50 ` [PATCH 4/9] net: add set_promisc function to enable/disable Promiscuous mode Tim Harvey
  2021-07-02  9:46   ` Ramon Fried
@ 2021-07-10 19:36   ` sbabic
  1 sibling, 0 replies; 25+ messages in thread
From: sbabic @ 2021-07-10 19:36 UTC (permalink / raw)
  To: Tim Harvey, u-boot

> Enabling promiscuous mode can be useful for DSA switches where each port
> has its own MAC address.
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
> Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 25+ messages in thread

* [PATCH 9/9] configs: imx8mm_venice_defconfig: add support for gbe switch
  2021-06-30 23:50 ` [PATCH 9/9] configs: imx8mm_venice_defconfig: add support for gbe switch Tim Harvey
@ 2021-07-10 19:37   ` sbabic
  0 siblings, 0 replies; 25+ messages in thread
From: sbabic @ 2021-07-10 19:37 UTC (permalink / raw)
  To: Tim Harvey, u-boot

> The imx8mm-venice-gw7901 board has an I2C connected KSZ9897S GbE switch
> with an IMX8MM FEC MAC master connected via RGMII_ID.
> Signed-off-by: Tim Harvey <tharvey@gateworks.com>
Applied to u-boot-imx, master, thanks !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic@denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2021-07-10 19:42 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-30 23:50 [PATCH 0/9] Add support for imx8mm-venice-gw7901 and DSA switch Tim Harvey
2021-06-30 23:50 ` [PATCH 1/9] board: gateworks: venice: add imx8mm-gw7901 support Tim Harvey
2021-07-10 19:35   ` sbabic
2021-06-30 23:50 ` [PATCH 2/9] net: fec: use device sequence vs index when fetching fec Tim Harvey
2021-07-02  9:44   ` Ramon Fried
2021-07-10 19:35   ` sbabic
2021-06-30 23:50 ` [PATCH 3/9] net: fec: set phy_of_node properly for fixed-link phy Tim Harvey
2021-07-02  9:44   ` Ramon Fried
2021-07-10 19:34   ` sbabic
2021-06-30 23:50 ` [PATCH 4/9] net: add set_promisc function to enable/disable Promiscuous mode Tim Harvey
2021-07-02  9:46   ` Ramon Fried
2021-07-10 19:36   ` sbabic
2021-06-30 23:50 ` [PATCH 5/9] net: fec: add set_promisc function Tim Harvey
2021-07-02  9:46   ` Ramon Fried
2021-07-10 19:35   ` sbabic
2021-06-30 23:50 ` [PATCH 6/9] net: dsa: enable master promisc mode if available and needed Tim Harvey
2021-07-02  9:47   ` Ramon Fried
2021-07-10 19:35   ` sbabic
2021-06-30 23:50 ` [PATCH 7/9] net: add support for KSZ9477/KSZ9897/KSZ9567 GbE switch Tim Harvey
2021-07-02  9:49   ` Ramon Fried
2021-07-10 19:35   ` sbabic
2021-06-30 23:50 ` [PATCH 8/9] arm: dts: imx8mm-venice-gw7901.dts: fix dsa switch configuration Tim Harvey
2021-07-10 19:35   ` sbabic
2021-06-30 23:50 ` [PATCH 9/9] configs: imx8mm_venice_defconfig: add support for gbe switch Tim Harvey
2021-07-10 19:37   ` sbabic

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.