blob: 8dd558b1bf25666dcaa6849073eac6db8f874bdf [file] [log] [blame]
Suneel Garapati53dc4482020-08-26 14:37:33 +02001// 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 */
25void 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 */
77void 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}