mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-03 21:48:15 +00:00 
			
		
		
		
	Adds support for Network Interface controllers found on OcteonTX SoC platforms. Signed-off-by: Suneel Garapati <sgarapati@marvell.com> Signed-off-by: Stefan Roese <sr@denx.de> Cc: Joe Hershberger <joe.hershberger@ni.com>
		
			
				
	
	
		
			125 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
// 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));
 | 
						|
	}
 | 
						|
}
 |