diff options
Diffstat (limited to 'roms/u-boot/drivers/net/octeontx/xcv.c')
-rw-r--r-- | roms/u-boot/drivers/net/octeontx/xcv.c | 124 |
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)); + } +} |