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