| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- // 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));
- }
- }
|