arm: mvebu: Add Armada 38x SERDES / PHY init code from Marvell bin_hdr
[platform/kernel/u-boot.git] / arch / arm / mach-mvebu / serdes / a38x / high_speed_env_spec-38x.c
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 }