1 /*
2  * Copyright (C) Marvell International Ltd. and its affiliates
3  *
4  * SPDX-License-Identifier:	GPL-2.0
5  */
6 
7 #include <common.h>
8 #include <spl.h>
9 #include <asm/io.h>
10 #include <asm/arch/cpu.h>
11 #include <asm/arch/soc.h>
12 
13 #include "high_speed_env_spec.h"
14 #include "sys_env_lib.h"
15 
16 #define SERDES_VERION	"2.0"
17 
18 u8 selectors_serdes_rev1_map[LAST_SERDES_TYPE][MAX_SERDES_LANES] = {
19 	/* 0  1    2    3    4    5 */
20 	{0x1, 0x1, NA,  NA,  NA,  NA},		/* PEX0 */
21 	{NA,  0x2, 0x1, NA,  0x1, NA},		/* PEX1 */
22 	{NA,  NA,  0x2, NA,  NA,  0x1},		/* PEX2 */
23 	{NA,  NA,  NA,  0x1, NA,  NA},		/* PEX3 */
24 	{0x2, 0x3, NA,  NA,  NA,  NA},		/* SATA0 */
25 	{NA,  NA,  0x3, NA,  0x2, NA},		/* SATA1 */
26 	{NA,  NA,  NA,  NA,  0x6, 0x2},		/* SATA2 */
27 	{NA,  NA,  NA,  0x3, NA,  NA},		/* SATA3 */
28 	{0x3, 0x4, NA,  NA,  NA,  NA},		/* SGMII0 */
29 	{NA,  0x5, 0x4, NA,  0x3, NA},		/* SGMII1 */
30 	{NA,  NA,  NA,  0x4, NA,  0x3},		/* SGMII2 */
31 	{NA,  0x7, NA,  NA,  NA,  NA},		/* QSGMII */
32 	{NA,  0x6, NA,  NA,  0x4, NA},		/* USB3_HOST0 */
33 	{NA,  NA,  NA,  0x5, NA,  0x4},		/* USB3_HOST1 */
34 	{NA,  NA,  NA,  0x6, 0x5, 0x5},		/* USB3_DEVICE */
35 	{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}		/* DEFAULT_SERDES */
36 };
37 
38 int hws_serdes_seq_init(void)
39 {
40 	DEBUG_INIT_FULL_S("\n### serdes_seq_init ###\n");
41 
42 	if (hws_serdes_seq_db_init() != MV_OK) {
43 		printf("hws_serdes_seq_init: Error: Serdes initialization fail\n");
44 		return MV_FAIL;
45 	}
46 
47 	return MV_OK;
48 }
49 
50 int serdes_power_up_ctrl_ext(u32 serdes_num, int serdes_power_up,
51 			     enum serdes_type serdes_type,
52 			     enum serdes_speed baud_rate,
53 			     enum serdes_mode serdes_mode,
54 			     enum ref_clock ref_clock)
55 {
56 	return MV_NOT_SUPPORTED;
57 }
58 
59 u32 hws_serdes_silicon_ref_clock_get(void)
60 {
61 	DEBUG_INIT_FULL_S("\n### hws_serdes_silicon_ref_clock_get ###\n");
62 
63 	return REF_CLOCK_25MHZ;
64 }
65 
66 u32 hws_serdes_get_max_lane(void)
67 {
68 	switch (sys_env_device_id_get()) {
69 	case MV_6811:		/* A381/A3282: 6811/6821: single/dual cpu */
70 		return 4;
71 	case MV_6810:
72 		return 5;
73 	case MV_6820:
74 	case MV_6828:
75 		return 6;
76 	default:		/* not the right module */
77 		printf("%s: Device ID Error, using 4 SerDes lanes\n",
78 		       __func__);
79 		return 4;
80 	}
81 	return 6;
82 }
83 
84 int hws_is_serdes_active(u8 lane_num)
85 {
86 	int ret = 1;
87 
88 	/* Maximum lane count for A388 (6828) is 6 */
89 	if (lane_num > 6)
90 		ret = 0;
91 
92 	/* 4th Lane (#4 on Device 6810 is not Active */
93 	if (sys_env_device_id_get() == MV_6810 && lane_num == 4) {
94 		printf("%s: Error: Lane#4 on Device 6810 is not Active.\n",
95 		       __func__);
96 		return 0;
97 	}
98 
99 	/*
100 	 * 6th Lane (#5) on Device 6810 is Active, even though 6810
101 	 * has only 5 lanes
102 	 */
103 	if (sys_env_device_id_get() == MV_6810 && lane_num == 5)
104 		return 1;
105 
106 	if (lane_num >= hws_serdes_get_max_lane())
107 		ret = 0;
108 
109 	return ret;
110 }
111 
112 int hws_get_ext_base_addr(u32 serdes_num, u32 base_addr, u32 unit_base_offset,
113 			  u32 *unit_base_reg, u32 *unit_offset)
114 {
115 	*unit_base_reg = base_addr;
116 	*unit_offset = unit_base_offset;
117 
118 	return MV_OK;
119 }
120 
121 /*
122  * hws_serdes_get_phy_selector_val
123  *
124  * DESCRIPTION: Get the mapping of Serdes Selector values according to the
125  *              Serdes revision number
126  * INPUT:    serdes_num - Serdes number
127  *           serdes_type - Serdes type
128  * OUTPUT: None
129  * RETURN:
130  *       Mapping of Serdes Selector values
131  */
132 u32 hws_serdes_get_phy_selector_val(int serdes_num,
133 				    enum serdes_type serdes_type)
134 {
135 	if (serdes_type >= LAST_SERDES_TYPE)
136 		return 0xff;
137 
138 	if (hws_ctrl_serdes_rev_get() == MV_SERDES_REV_1_2) {
139 		return selectors_serdes_rev1_map
140 			[serdes_type][serdes_num];
141 	} else
142 		return selectors_serdes_rev2_map
143 			[serdes_type][serdes_num];
144 }
145 
146 u32 hws_get_physical_serdes_num(u32 serdes_num)
147 {
148 	if ((serdes_num == 4) && (sys_env_device_id_get() == MV_6810)) {
149 		/*
150 		 * For 6810, there are 5 Serdes and Serdes Num 4 doesn't
151 		 * exist. Instead Serdes Num 5 is connected.
152 		 */
153 		return 5;
154 	} else {
155 		return serdes_num;
156 	}
157 }
158