1 // SPDX-License-Identifier:    GPL-2.0
2 /*
3  * Copyright (C) 2018 Marvell International Ltd.
4  */
5 
6 #include <config.h>
7 #include <dm.h>
8 #include <errno.h>
9 #include <fdt_support.h>
10 #include <pci.h>
11 #include <malloc.h>
12 #include <miiphy.h>
13 #include <misc.h>
14 #include <net.h>
15 #include <netdev.h>
16 #include <asm/io.h>
17 #include <linux/delay.h>
18 #include <linux/libfdt.h>
19 
20 #include <asm/arch/csrs/csrs-xcv.h>
21 
22 #define XCVX_BASE		0x87E0DB000000ULL
23 
24 /* Initialize XCV block */
xcv_init_hw(void)25 void xcv_init_hw(void)
26 {
27 	union xcvx_reset reset;
28 	union xcvx_dll_ctl xcv_dll_ctl;
29 
30 	/* Take the DLL out of reset */
31 	reset.u = readq(XCVX_BASE + XCVX_RESET(0));
32 	reset.s.dllrst = 0;
33 	writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
34 
35 	/* Take the clock tree out of reset */
36 	reset.u = readq(XCVX_BASE + XCVX_RESET(0));
37 	reset.s.clkrst = 0;
38 	writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
39 
40 	/* Once the 125MHz ref clock is stable, wait 10us for DLL to lock */
41 	udelay(10);
42 
43 	/* Optionally, bypass the DLL setting */
44 	xcv_dll_ctl.u = readq(XCVX_BASE + XCVX_DLL_CTL(0));
45 	xcv_dll_ctl.s.clkrx_set = 0;
46 	xcv_dll_ctl.s.clkrx_byp = 1;
47 	xcv_dll_ctl.s.clktx_byp = 0;
48 	writeq(xcv_dll_ctl.u, XCVX_BASE + XCVX_DLL_CTL(0));
49 
50 	/* Enable the compensation controller */
51 	reset.u = readq(XCVX_BASE + XCVX_RESET(0));
52 	reset.s.comp = 1;
53 	writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
54 	reset.u = readq(XCVX_BASE + XCVX_RESET(0));
55 
56 	/* Wait for 1040 reference clock cycles for the compensation state
57 	 * machine lock.
58 	 */
59 	udelay(100);
60 
61 	/* Enable the XCV block */
62 	reset.u = readq(XCVX_BASE + XCVX_RESET(0));
63 	reset.s.enable = 1;
64 	writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
65 
66 	/* set XCV(0)_RESET[CLKRST] to 1 */
67 	reset.u = readq(XCVX_BASE + XCVX_RESET(0));
68 	reset.s.clkrst = 1;
69 	writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
70 }
71 
72 /*
73  * Configure XCV link based on the speed
74  * link_up   : Set to 1 when link is up otherwise 0
75  * link_speed: The speed of the link.
76  */
xcv_setup_link(bool link_up,int link_speed)77 void xcv_setup_link(bool link_up, int link_speed)
78 {
79 	union xcvx_ctl xcv_ctl;
80 	union xcvx_reset reset;
81 	union xcvx_batch_crd_ret xcv_crd_ret;
82 	int speed = 2;
83 
84 	/* Check RGMII link */
85 	if (link_speed == 100)
86 		speed = 1;
87 	else if (link_speed == 10)
88 		speed = 0;
89 
90 	if (link_up) {
91 		/* Set operating speed */
92 		xcv_ctl.u = readq(XCVX_BASE + XCVX_CTL(0));
93 		xcv_ctl.s.speed = speed;
94 		writeq(xcv_ctl.u, XCVX_BASE + XCVX_CTL(0));
95 
96 		/* Datapaths come out of reset
97 		 * - The datapath resets will disengage BGX from the
98 		 *   RGMII interface
99 		 * - XCV will continue to return TX credits for each tick
100 		 *   that is sent on the TX data path
101 		 */
102 		reset.u = readq(XCVX_BASE + XCVX_RESET(0));
103 		reset.s.tx_dat_rst_n = 1;
104 		reset.s.rx_dat_rst_n = 1;
105 		writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
106 
107 		/* Enable packet flow */
108 		reset.u = readq(XCVX_BASE + XCVX_RESET(0));
109 		reset.s.tx_pkt_rst_n = 1;
110 		reset.s.rx_pkt_rst_n = 1;
111 		writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
112 
113 		xcv_crd_ret.u = readq(XCVX_BASE + XCVX_BATCH_CRD_RET(0));
114 		xcv_crd_ret.s.crd_ret = 1;
115 		writeq(xcv_crd_ret.u, XCVX_BASE + XCVX_BATCH_CRD_RET(0));
116 	} else {
117 		/* Enable packet flow */
118 		reset.u = readq(XCVX_BASE + XCVX_RESET(0));
119 		reset.s.tx_pkt_rst_n = 0;
120 		reset.s.rx_pkt_rst_n = 0;
121 		writeq(reset.u, XCVX_BASE + XCVX_RESET(0));
122 		reset.u = readq(XCVX_BASE + XCVX_RESET(0));
123 	}
124 }
125