aboutsummaryrefslogtreecommitdiffstats
path: root/roms/u-boot/drivers/net/octeontx/xcv.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/u-boot/drivers/net/octeontx/xcv.c')
-rw-r--r--roms/u-boot/drivers/net/octeontx/xcv.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/net/octeontx/xcv.c b/roms/u-boot/drivers/net/octeontx/xcv.c
new file mode 100644
index 000000000..8dd558b1b
--- /dev/null
+++ b/roms/u-boot/drivers/net/octeontx/xcv.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Marvell International Ltd.
+ */
+
+#include <config.h>
+#include <dm.h>
+#include <errno.h>
+#include <fdt_support.h>
+#include <pci.h>
+#include <malloc.h>
+#include <miiphy.h>
+#include <misc.h>
+#include <net.h>
+#include <netdev.h>
+#include <asm/io.h>
+#include <linux/delay.h>
+#include <linux/libfdt.h>
+
+#include <asm/arch/csrs/csrs-xcv.h>
+
+#define XCVX_BASE 0x87E0DB000000ULL
+
+/* Initialize XCV block */
+void xcv_init_hw(void)
+{
+ union xcvx_reset reset;
+ union xcvx_dll_ctl xcv_dll_ctl;
+
+ /* Take the DLL out of reset */
+ reset.u = readq(XCVX_BASE + XCVX_RESET(0));
+ reset.s.dllrst = 0;
+ writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
+
+ /* Take the clock tree out of reset */
+ reset.u = readq(XCVX_BASE + XCVX_RESET(0));
+ reset.s.clkrst = 0;
+ writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
+
+ /* Once the 125MHz ref clock is stable, wait 10us for DLL to lock */
+ udelay(10);
+
+ /* Optionally, bypass the DLL setting */
+ xcv_dll_ctl.u = readq(XCVX_BASE + XCVX_DLL_CTL(0));
+ xcv_dll_ctl.s.clkrx_set = 0;
+ xcv_dll_ctl.s.clkrx_byp = 1;
+ xcv_dll_ctl.s.clktx_byp = 0;
+ writeq(xcv_dll_ctl.u, XCVX_BASE + XCVX_DLL_CTL(0));
+
+ /* Enable the compensation controller */
+ reset.u = readq(XCVX_BASE + XCVX_RESET(0));
+ reset.s.comp = 1;
+ writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
+ reset.u = readq(XCVX_BASE + XCVX_RESET(0));
+
+ /* Wait for 1040 reference clock cycles for the compensation state
+ * machine lock.
+ */
+ udelay(100);
+
+ /* Enable the XCV block */
+ reset.u = readq(XCVX_BASE + XCVX_RESET(0));
+ reset.s.enable = 1;
+ writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
+
+ /* set XCV(0)_RESET[CLKRST] to 1 */
+ reset.u = readq(XCVX_BASE + XCVX_RESET(0));
+ reset.s.clkrst = 1;
+ writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
+}
+
+/*
+ * Configure XCV link based on the speed
+ * link_up : Set to 1 when link is up otherwise 0
+ * link_speed: The speed of the link.
+ */
+void xcv_setup_link(bool link_up, int link_speed)
+{
+ union xcvx_ctl xcv_ctl;
+ union xcvx_reset reset;
+ union xcvx_batch_crd_ret xcv_crd_ret;
+ int speed = 2;
+
+ /* Check RGMII link */
+ if (link_speed == 100)
+ speed = 1;
+ else if (link_speed == 10)
+ speed = 0;
+
+ if (link_up) {
+ /* Set operating speed */
+ xcv_ctl.u = readq(XCVX_BASE + XCVX_CTL(0));
+ xcv_ctl.s.speed = speed;
+ writeq(xcv_ctl.u, XCVX_BASE + XCVX_CTL(0));
+
+ /* Datapaths come out of reset
+ * - The datapath resets will disengage BGX from the
+ * RGMII interface
+ * - XCV will continue to return TX credits for each tick
+ * that is sent on the TX data path
+ */
+ reset.u = readq(XCVX_BASE + XCVX_RESET(0));
+ reset.s.tx_dat_rst_n = 1;
+ reset.s.rx_dat_rst_n = 1;
+ writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
+
+ /* Enable packet flow */
+ reset.u = readq(XCVX_BASE + XCVX_RESET(0));
+ reset.s.tx_pkt_rst_n = 1;
+ reset.s.rx_pkt_rst_n = 1;
+ writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
+
+ xcv_crd_ret.u = readq(XCVX_BASE + XCVX_BATCH_CRD_RET(0));
+ xcv_crd_ret.s.crd_ret = 1;
+ writeq(xcv_crd_ret.u, XCVX_BASE + XCVX_BATCH_CRD_RET(0));
+ } else {
+ /* Enable packet flow */
+ reset.u = readq(XCVX_BASE + XCVX_RESET(0));
+ reset.s.tx_pkt_rst_n = 0;
+ reset.s.rx_pkt_rst_n = 0;
+ writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
+ reset.u = readq(XCVX_BASE + XCVX_RESET(0));
+ }
+}