--- /dev/null
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Device Tree file for Travese Ten64 (LS1088) board
+ * Based on fsl-ls1088a-rdb.dts
+ * Copyright 2017-2020 NXP
+ * Copyright 2019-2021 Traverse Technologies
+ *
+ * Author: Mathew McBride <matt@traverse.com.au>
+ */
+
+/dts-v1/;
+
+#include "fsl-ls1088a.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Traverse Ten64";
+ compatible = "traverse,ten64", "fsl,ls1088a";
+
+ aliases {
+ spi0 = &qspi;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ buttons {
+ compatible = "gpio-keys";
+
+ /* Fired by system controller when
+ * external power off (e.g ATX Power Button)
+ * asserted
+ */
+ powerdn {
+ label = "External Power Down";
+ gpios = <&gpio1 17 GPIO_ACTIVE_LOW>;
+ interrupts = <&gpio1 17 IRQ_TYPE_EDGE_FALLING>;
+ linux,code = <KEY_POWER>;
+ };
+
+ /* Rear Panel 'ADMIN' button (GPIO_H) */
+ admin {
+ label = "ADMIN button";
+ gpios = <&gpio3 8 GPIO_ACTIVE_HIGH>;
+ interrupts = <&gpio3 8 IRQ_TYPE_EDGE_RISING>;
+ linux,code = <KEY_WPS_BUTTON>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ sfp1down {
+ label = "ten64:green:sfp1:down";
+ gpios = <&gpio3 11 GPIO_ACTIVE_HIGH>;
+ };
+
+ sfp2up {
+ label = "ten64:green:sfp2:up";
+ gpios = <&gpio3 12 GPIO_ACTIVE_HIGH>;
+ };
+
+ admin {
+ label = "ten64:admin";
+ gpios = <&sfpgpio 12 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ sfp_xg0: dpmac2-sfp {
+ compatible = "sff,sfp";
+ i2c-bus = <&sfplower_i2c>;
+ tx-fault-gpios = <&sfpgpio 0 GPIO_ACTIVE_HIGH>;
+ tx-disable-gpios = <&sfpgpio 1 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sfpgpio 2 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sfpgpio 3 GPIO_ACTIVE_HIGH>;
+ maximum-power-milliwatt = <2000>;
+ };
+
+ sfp_xg1: dpmac1-sfp {
+ compatible = "sff,sfp";
+ i2c-bus = <&sfpupper_i2c>;
+ tx-fault-gpios = <&sfpgpio 4 GPIO_ACTIVE_HIGH>;
+ tx-disable-gpios = <&sfpgpio 5 GPIO_ACTIVE_HIGH>;
+ mod-def0-gpios = <&sfpgpio 6 GPIO_ACTIVE_LOW>;
+ los-gpios = <&sfpgpio 7 GPIO_ACTIVE_HIGH>;
+ maximum-power-milliwatt = <2000>;
+ };
+};
+
+/* XG1 - Upper SFP */
+&dpmac1 {
+ sfp = <&sfp_xg1>;
+ phy-connection-type = "10gbase-r";
+ managed = "in-band-status";
+ status = "okay";
+};
+
+/* XG0 - Lower SFP */
+&dpmac2 {
+ sfp = <&sfp_xg0>;
+ phy-connection-type = "10gbase-r";
+ managed = "in-band-status";
+ status = "okay";
+};
+
+/* DPMAC3..6 is GE4 to GE8 */
+&dpmac3 {
+ phy-handle = <&mdio1_phy5>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ status = "okay";
+};
+
+&dpmac4 {
+ phy-handle = <&mdio1_phy6>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ status = "okay";
+};
+
+&dpmac5 {
+ phy-handle = <&mdio1_phy7>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ status = "okay";
+};
+
+&dpmac6 {
+ phy-handle = <&mdio1_phy8>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ status = "okay";
+};
+
+/* DPMAC7..10 is GE0 to GE3 */
+&dpmac7 {
+ phy-handle = <&mdio1_phy1>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ status = "okay";
+};
+
+&dpmac8 {
+ phy-handle = <&mdio1_phy2>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ status = "okay";
+};
+
+&dpmac9 {
+ phy-handle = <&mdio1_phy3>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ status = "okay";
+};
+
+&dpmac10 {
+ phy-handle = <&mdio1_phy4>;
+ phy-connection-type = "qsgmii";
+ managed = "in-band-status";
+ status = "okay";
+};
+
+&serial0 {
+ status = "okay";
+};
+
+&serial1 {
+ status = "okay";
+};
+
+&emdio1 {
+ status = "okay";
+
+ mdio1_phy5: ethernet-phy@c {
+ reg = <0xc>;
+ };
+
+ mdio1_phy6: ethernet-phy@d {
+ reg = <0xd>;
+ };
+
+ mdio1_phy7: ethernet-phy@e {
+ reg = <0xe>;
+ };
+
+ mdio1_phy8: ethernet-phy@f {
+ reg = <0xf>;
+ };
+
+ mdio1_phy1: ethernet-phy@1c {
+ reg = <0x1c>;
+ };
+
+ mdio1_phy2: ethernet-phy@1d {
+ reg = <0x1d>;
+ };
+
+ mdio1_phy3: ethernet-phy@1e {
+ reg = <0x1e>;
+ };
+
+ mdio1_phy4: ethernet-phy@1f {
+ reg = <0x1f>;
+ };
+};
+
+&esdhc {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ sfpgpio: gpio@76 {
+ compatible = "ti,tca9539";
+ reg = <0x76>;
+ #gpio-cells = <2>;
+ gpio-controller;
+
+ admin_led_lower {
+ gpio-hog;
+ gpios = <13 GPIO_ACTIVE_HIGH>;
+ output-low;
+ };
+ };
+
+ at97sc: tpm@29 {
+ compatible = "atmel,at97sc3204t";
+ reg = <0x29>;
+ };
+
+ uc: board-controller@7e {
+ compatible = "traverse,ten64-controller";
+ reg = <0x7e>;
+ };
+};
+
+&i2c2 {
+ status = "okay";
+
+ rx8035: rtc@32 {
+ compatible = "epson,rx8035";
+ reg = <0x32>;
+ };
+};
+
+&i2c3 {
+ status = "okay";
+
+ i2c-switch@70 {
+ compatible = "nxp,pca9540";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x70>;
+
+ sfpupper_i2c: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ sfplower_i2c: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+ };
+};
+
+&qspi {
+ status = "okay";
+
+ en25s64: flash@0 {
+ compatible = "jedec,spi-nor";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0>;
+ spi-max-frequency = <20000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "bl2";
+ reg = <0 0x100000>;
+ };
+
+ partition@100000 {
+ label = "bl3";
+ reg = <0x100000 0x200000>;
+ };
+
+ partition@300000 {
+ label = "mcfirmware";
+ reg = <0x300000 0x200000>;
+ };
+
+ partition@500000 {
+ label = "ubootenv";
+ reg = <0x500000 0x80000>;
+ };
+
+ partition@580000 {
+ label = "dpl";
+ reg = <0x580000 0x40000>;
+ };
+
+ partition@5C0000 {
+ label = "dpc";
+ reg = <0x5C0000 0x40000>;
+ };
+
+ partition@600000 {
+ label = "devicetree";
+ reg = <0x600000 0x40000>;
+ };
+ };
+ };
+
+ nand: flash@1 {
+ compatible = "spi-nand";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <1>;
+ spi-max-frequency = <20000000>;
+ spi-rx-bus-width = <4>;
+ spi-tx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* reserved for future boot direct from NAND flash
+ * (this would use the same layout as the 8MiB NOR flash)
+ */
+ partition@0 {
+ label = "nand-boot-reserved";
+ reg = <0 0x800000>;
+ };
+
+ /* recovery / install environment */
+ partition@800000 {
+ label = "recovery";
+ reg = <0x800000 0x2000000>;
+ };
+
+ /* ubia (first OpenWrt) - a/b names to prevent confusion with ubi0/1/etc. */
+ partition@2800000 {
+ label = "ubia";
+ reg = <0x2800000 0x6C00000>;
+ };
+
+ /* ubib (second OpenWrt) */
+ partition@9400000 {
+ label = "ubib";
+ reg = <0x9400000 0x6C00000>;
+ };
+ };
+ };
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
--- /dev/null
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Traverse Ten64 Family board
+ * Copyright 2017-2018 NXP
+ * Copyright 2019-2021 Traverse Technologies
+ */
+#include <common.h>
+#include <dm/uclass.h>
+#include <env.h>
+#include <i2c.h>
+#include <init.h>
+#include <log.h>
+#include <malloc.h>
+#include <errno.h>
+#include <misc.h>
+#include <netdev.h>
+#include <fsl_ifc.h>
+#include <fsl_ddr.h>
+#include <fsl_sec.h>
+#include <asm/global_data.h>
+#include <asm/io.h>
+#include <fdt_support.h>
+#include <linux/delay.h>
+#include <linux/libfdt.h>
+#include <fsl-mc/fsl_mc.h>
+#include <env_internal.h>
+#include <asm/arch-fsl-layerscape/soc.h>
+#include <asm/arch/ppa.h>
+#include <hwconfig.h>
+#include <asm/arch/fsl_serdes.h>
+#include <asm/arch/soc.h>
+#include <asm/arch-fsl-layerscape/fsl_icid.h>
+
+#include <fsl_immap.h>
+
+#include "../common/ten64-controller.h"
+
+#define I2C_RETIMER_ADDR 0x27
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int ten64_read_board_info(struct t64uc_board_info *);
+static void ten64_set_macaddrs_from_board_info(struct t64uc_board_info *);
+static void ten64_board_retimer_ds110df410_init(void);
+
+enum {
+ TEN64_BOARD_REV_A = 0xFF,
+ TEN64_BOARD_REV_B = 0xFE,
+ TEN64_BOARD_REV_C = 0xFD
+};
+
+#define RESV_MEM_IN_BANK(b) (gd->arch.resv_ram >= base[b] && \
+ gd->arch.resv_ram < base[b] + size[b])
+
+int board_early_init_f(void)
+{
+ fsl_lsch3_early_init_f();
+ return 0;
+}
+
+static u32 ten64_get_board_rev(void)
+{
+ struct ccsr_gur *dcfg = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+ u32 board_rev_in = in_le32(&dcfg->gpporcr1);
+ return board_rev_in;
+}
+
+int checkboard(void)
+{
+ enum boot_src src = get_boot_src();
+ char boardmodel[32];
+ struct t64uc_board_info boardinfo;
+ u32 board_rev = ten64_get_board_rev();
+
+ switch (board_rev) {
+ case TEN64_BOARD_REV_A:
+ snprintf(boardmodel, 32, "1064-0201A (Alpha)");
+ break;
+ case TEN64_BOARD_REV_B:
+ snprintf(boardmodel, 32, "1064-0201B (Beta)");
+ break;
+ case TEN64_BOARD_REV_C:
+ snprintf(boardmodel, 32, "1064-0201C");
+ break;
+ default:
+ snprintf(boardmodel, 32, "1064 Revision %X", (0xFF - board_rev));
+ break;
+ }
+
+ printf("Board: %s, boot from ", boardmodel);
+ if (src == BOOT_SOURCE_SD_MMC)
+ puts("SD card\n");
+ else if (src == BOOT_SOURCE_QSPI_NOR)
+ puts("QSPI\n");
+ else
+ printf("Unknown boot source %d\n", src);
+
+ puts("Controller: ");
+ if (CONFIG_IS_ENABLED(TEN64_CONTROLLER)) {
+ /* Driver not compatible with alpha/beta board MCU firmware */
+ if (board_rev <= TEN64_BOARD_REV_C) {
+ if (ten64_read_board_info(&boardinfo)) {
+ puts("ERROR: unable to communicate\n");
+ } else {
+ printf("firmware %d.%d.%d\n",
+ boardinfo.fwversion_major,
+ boardinfo.fwversion_minor,
+ boardinfo.fwversion_patch);
+ ten64_set_macaddrs_from_board_info(&boardinfo);
+ }
+ } else {
+ puts("not supported on this board revision\n");
+ }
+ } else {
+ puts("driver not enabled (no MAC addresses or other information will be read)\n");
+ }
+
+ return 0;
+}
+
+int board_init(void)
+{
+ init_final_memctl_regs();
+
+ if (CONFIG_IS_ENABLED(FSL_CAAM))
+ sec_init();
+
+ return 0;
+}
+
+int fsl_initdram(void)
+{
+ gd->ram_size = tfa_get_dram_size();
+
+ if (!gd->ram_size)
+ gd->ram_size = fsl_ddr_sdram_size();
+
+ return 0;
+}
+
+void detail_board_ddr_info(void)
+{
+ puts("\nDDR ");
+ print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, "");
+ print_ddr_info(0);
+}
+
+void board_quiesce_devices(void)
+{
+ if (IS_ENABLED(CONFIG_FSL_MC_ENET))
+ fsl_mc_ldpaa_exit(gd->bd);
+}
+
+void fdt_fixup_board_enet(void *fdt)
+{
+ int offset;
+
+ offset = fdt_path_offset(fdt, "/fsl-mc");
+
+ if (offset < 0)
+ offset = fdt_path_offset(fdt, "/soc/fsl-mc");
+
+ if (offset < 0) {
+ printf("%s: ERROR: fsl-mc node not found in device tree (error %d)\n",
+ __func__, offset);
+ return;
+ }
+
+ if (get_mc_boot_status() == 0 &&
+ (is_lazy_dpl_addr_valid() || get_dpl_apply_status() == 0))
+ fdt_status_okay(fdt, offset);
+ else
+ fdt_status_fail(fdt, offset);
+}
+
+/* Called after SoC board_late_init in fsl-layerscape/soc.c */
+int fsl_board_late_init(void)
+{
+ ten64_board_retimer_ds110df410_init();
+ return 0;
+}
+
+int ft_board_setup(void *blob, struct bd_info *bd)
+{
+ int i;
+ u16 mc_memory_bank = 0;
+
+ u64 *base;
+ u64 *size;
+ u64 mc_memory_base = 0;
+ u64 mc_memory_size = 0;
+ u16 total_memory_banks;
+
+ debug("%s blob=0x%p\n", __func__, blob);
+
+ ft_cpu_setup(blob, bd);
+
+ fdt_fixup_mc_ddr(&mc_memory_base, &mc_memory_size);
+
+ if (mc_memory_base != 0)
+ mc_memory_bank++;
+
+ total_memory_banks = CONFIG_NR_DRAM_BANKS + mc_memory_bank;
+
+ base = calloc(total_memory_banks, sizeof(u64));
+ size = calloc(total_memory_banks, sizeof(u64));
+
+ /* fixup DT for the two GPP DDR banks */
+ for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
+ base[i] = gd->bd->bi_dram[i].start;
+ size[i] = gd->bd->bi_dram[i].size;
+ /* reduce size if reserved memory is within this bank */
+ if (CONFIG_IS_ENABLED(RESV_RAM) && RESV_MEM_IN_BANK(i))
+ size[i] = gd->arch.resv_ram - base[i];
+ }
+
+ if (mc_memory_base != 0) {
+ for (i = 0; i <= total_memory_banks; i++) {
+ if (base[i] == 0 && size[i] == 0) {
+ base[i] = mc_memory_base;
+ size[i] = mc_memory_size;
+ break;
+ }
+ }
+ }
+
+ fdt_fixup_memory_banks(blob, base, size, total_memory_banks);
+
+ fdt_fsl_mc_fixup_iommu_map_entry(blob);
+
+ if (CONFIG_IS_ENABLED(FSL_MC_ENET))
+ fdt_fixup_board_enet(blob);
+
+ fdt_fixup_icid(blob);
+
+ return 0;
+}
+
+#define MACADDRBITS(a, b) (u8)(((a) >> (b)) & 0xFF)
+
+/** Probe and return a udevice for the Ten64 board microcontroller.
+ * Optionally, return the I2C bus the microcontroller resides on
+ * @i2c_bus_out: return I2C bus device handle in this pointer
+ */
+static int ten64_get_micro_udevice(struct udevice **ucdev, struct udevice **i2c_bus_out)
+{
+ int ret;
+ struct udevice *i2cbus;
+
+ ret = uclass_get_device_by_seq(UCLASS_I2C, 0, &i2cbus);
+ if (ret) {
+ printf("%s: Could not get I2C UCLASS", __func__);
+ return ret;
+ }
+ if (i2c_bus_out)
+ *i2c_bus_out = i2cbus;
+
+ ret = dm_i2c_probe(i2cbus, 0x7E, DM_I2C_CHIP_RD_ADDRESS, ucdev);
+ if (ret) {
+ printf("%s: Could not get microcontroller device\n", __func__);
+ return ret;
+ }
+ return ret;
+}
+
+static int ten64_read_board_info(struct t64uc_board_info *boardinfo)
+{
+ struct udevice *ucdev;
+ int ret;
+
+ ret = ten64_get_micro_udevice(&ucdev, NULL);
+ if (ret)
+ return ret;
+
+ ret = misc_call(ucdev, TEN64_CNTRL_GET_BOARD_INFO, NULL, 0, (void *)boardinfo, 0);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static void ten64_set_macaddrs_from_board_info(struct t64uc_board_info *boardinfo)
+{
+ char ethaddr[18];
+ char enetvar[10];
+ u8 intfidx, this_dpmac_num;
+ u64 macaddr = 0;
+ /* We will copy the MAC address returned from the
+ * uC (48 bits) into the u64 macaddr
+ */
+ u8 *macaddr_bytes = (u8 *)&macaddr + 2;
+
+ /** MAC addresses are allocated in order of the physical port numbers,
+ * DPMAC7->10 is "eth0" through "eth3"
+ * DPMAC3->6 is "eth4" through "eth7"
+ * DPMAC2 and 1 are "eth8" and "eth9" respectively
+ */
+ int allocation_order[10] = {7, 8, 9, 10, 3, 4, 5, 6, 2, 1};
+
+ memcpy(macaddr_bytes, boardinfo->mac, 6);
+ /* MAC address bytes from uC are in big endian,
+ * convert to CPU
+ */
+ macaddr = __be64_to_cpu(macaddr);
+
+ for (intfidx = 0; intfidx < 10; intfidx++) {
+ snprintf(ethaddr, 18, "%02X:%02X:%02X:%02X:%02X:%02X",
+ MACADDRBITS(macaddr, 40),
+ MACADDRBITS(macaddr, 32),
+ MACADDRBITS(macaddr, 24),
+ MACADDRBITS(macaddr, 16),
+ MACADDRBITS(macaddr, 8),
+ MACADDRBITS(macaddr, 0));
+
+ this_dpmac_num = allocation_order[intfidx];
+ printf("DPMAC%d: %s\n", this_dpmac_num, ethaddr);
+ snprintf(enetvar, 10,
+ (this_dpmac_num != 1) ? "eth%daddr" : "ethaddr",
+ this_dpmac_num - 1);
+ macaddr++;
+
+ if (!env_get(enetvar))
+ env_set(enetvar, ethaddr);
+ }
+}
+
+/* The retimer (DS110DF410) is one of the devices without
+ * a RESET line, but a power switch is on the board
+ * allowing it to be reset via uC command
+ */
+static int board_cycle_retimer(struct udevice **retim_dev)
+{
+ int ret;
+ u8 loop;
+ struct udevice *uc_dev;
+ struct udevice *i2cbus;
+
+ ret = ten64_get_micro_udevice(&uc_dev, &i2cbus);
+ if (ret)
+ return ret;
+
+ ret = dm_i2c_probe(i2cbus, I2C_RETIMER_ADDR, 0, retim_dev);
+ if (ret == 0) {
+ puts("(retimer on, resetting...) ");
+
+ ret = misc_call(uc_dev, TEN64_CNTRL_10G_OFF, NULL, 0, NULL, 0);
+ mdelay(1000);
+ }
+
+ ret = misc_call(uc_dev, TEN64_CNTRL_10G_ON, NULL, 0, NULL, 0);
+
+ // Wait for retimer to come back
+ for (loop = 0; loop < 5; loop++) {
+ ret = dm_i2c_probe(i2cbus, I2C_RETIMER_ADDR, 0, retim_dev);
+ if (ret == 0)
+ return 0;
+ mdelay(500);
+ }
+
+ return -ENOSYS;
+}
+
+/* ten64_board_retimer_ds110df410_init() - Configure the 10G retimer
+ * Adopted from the t102xqds board file
+ */
+static void ten64_board_retimer_ds110df410_init(void)
+{
+ u8 reg;
+ int ret;
+ struct udevice *retim_dev;
+ u32 board_rev = ten64_get_board_rev();
+
+ puts("Retimer: ");
+ /* Retimer power cycle not implemented on early board
+ * revisions/controller firmwares
+ */
+ if (CONFIG_IS_ENABLED(TEN64_CONTROLLER) &&
+ board_rev >= TEN64_BOARD_REV_C) {
+ ret = board_cycle_retimer(&retim_dev);
+ if (ret) {
+ puts("Retimer power on failed\n");
+ return;
+ }
+ }
+
+ /* Access to Control/Shared register */
+ reg = 0x0;
+
+ ret = dm_i2c_write(retim_dev, 0xff, ®, 1);
+ if (ret) {
+ printf("Error writing to retimer register (error %d)\n", ret);
+ return;
+ }
+
+ /* Read device revision and ID */
+ dm_i2c_read(retim_dev, 1, ®, 1);
+ if (reg == 0xF0)
+ puts("DS110DF410 found\n");
+ else
+ printf("Unknown retimer 0x%xn\n", reg);
+
+ /* Enable Broadcast */
+ reg = 0x0c;
+ dm_i2c_write(retim_dev, 0xff, ®, 1);
+
+ /* Perform a full reset (state, channel and clock)
+ * for all channels
+ * as the DS110DF410 does not have a RESET line
+ */
+ dm_i2c_read(retim_dev, 0, ®, 1);
+ reg |= 0x7;
+ dm_i2c_write(retim_dev, 0, ®, 1);
+
+ /* Set rate/subrate = 0 */
+ reg = 0x6;
+ dm_i2c_write(retim_dev, 0x2F, ®, 1);
+
+ /* Set data rate as 10.3125 Gbps */
+ reg = 0x0;
+ dm_i2c_write(retim_dev, 0x60, ®, 1);
+ reg = 0xb2;
+ dm_i2c_write(retim_dev, 0x61, ®, 1);
+ reg = 0x90;
+ dm_i2c_write(retim_dev, 0x62, ®, 1);
+ reg = 0xb3;
+ dm_i2c_write(retim_dev, 0x63, ®, 1);
+ reg = 0xff;
+ dm_i2c_write(retim_dev, 0x64, ®, 1);
+
+ /* Invert channel 2 (Lower SFP TX to CPU) due to the SFP being inverted */
+ reg = 0x05;
+ dm_i2c_write(retim_dev, 0xFF, ®, 1);
+ dm_i2c_read(retim_dev, 0x1F, ®, 1);
+ reg |= 0x80;
+ dm_i2c_write(retim_dev, 0x1F, ®, 1);
+
+ puts("OK\n");
+}