1 /***********************license start***********************************
2 * Copyright (c) 2003-2016 Cavium Inc. ([email protected]). All rights
3 * reserved.
4 *
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 *
18 * * Neither the name of Cavium Inc. nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
21 * permission.
22 *
23 * This Software, including technical data, may be subject to U.S. export
24 * control laws, including the U.S. Export Administration Act and its
25 * associated regulations, and may be subject to export or import
26 * regulations in other countries.
27 *
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
31 * TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
32 * REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
33 * DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
34 * OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
35 * PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
36 * QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
37 * ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
39 #include <bdk.h>
40 #include <libbdk-hal/if/bdk-if.h>
41 #include <libbdk-hal/bdk-mdio.h>
42 #include <libbdk-hal/bdk-qlm.h>
43
44 #define VSC_PHY_STD_PAGE (0x0)
45 #define VSC_PHY_EXT1_PAGE (0x1)
46 #define VSC_PHY_EXT2_PAGE (0x2)
47 #define VSC_PHY_EXT3_PAGE (0x3)
48 #define VSC_PHY_EXT4_PAGE (0x4)
49 #define VSC_PHY_GPIO_PAGE (0x10)
50 #define VSC_PHY_TEST_PAGE (0x2A30)
51 #define VSC_PHY_TR_PAGE (0x52B5)
52
53 const uint16_t init_script_rev_a[] = {
54 // Op, Page, Reg, Value, Mask
55 // 0, 1, 2, 3, 4
56 // --, ------, ----, ------, -----
57 0, 0x0000, 0x1f, 0x0000, 0xffff,
58 1, 0x0000, 0x16, 0x0001, 0x0001,
59 0, 0x0001, 0x1f, 0x2A30, 0xffff,
60 1, 0x2A30, 0x08, 0x8000, 0x8000,
61 0, 0x2A30, 0x1f, 0x52B5, 0xffff,
62 0, 0x52B5, 0x12, 0x0068, 0xffff,
63 0, 0x52B5, 0x11, 0x8980, 0xffff,
64 0, 0x52B5, 0x10, 0x8f90, 0xffff,
65 0, 0x52B5, 0x12, 0x0000, 0xffff,
66 0, 0x52B5, 0x11, 0x0003, 0xffff,
67 0, 0x52B5, 0x10, 0x8796, 0xffff,
68 0, 0x52B5, 0x12, 0x0050, 0xffff,
69 0, 0x52B5, 0x11, 0x100f, 0xffff,
70 0, 0x52B5, 0x10, 0x87fa, 0xffff,
71 0, 0x52B5, 0x1f, 0x2A30, 0xffff,
72 1, 0x2A30, 0x08, 0x0000, 0x8000,
73 0, 0x2A30, 0x1f, 0x0000, 0xffff,
74 1, 0x0000, 0x16, 0x0000, 0x0001,
75 0xf, 0xffff, 0xff, 0xffff, 0xffff
76 };
77
wr_masked(bdk_node_t node,int mdio_bus,int phy_addr,int reg,int value,int mask)78 static void wr_masked(bdk_node_t node, int mdio_bus, int phy_addr, int reg, int value, int mask)
79 {
80 int nmask = ~mask;
81 int old = bdk_mdio_read(node, mdio_bus, phy_addr, reg);
82 int vmask = value & mask;
83 int newv = old & nmask;
84 newv = newv | vmask;
85 bdk_mdio_write(node, mdio_bus, phy_addr, reg, newv);
86 }
vitesse_init_script(bdk_node_t node,int mdio_bus,int phy_addr)87 static void vitesse_init_script(bdk_node_t node, int mdio_bus, int phy_addr)
88 {
89 const uint16_t *ptr;
90 uint16_t reg_addr;
91 uint16_t reg_val;
92 uint16_t mask;
93
94 BDK_TRACE(PHY,"In %s\n",__func__);
95 BDK_TRACE(PHY,"Loading init script for VSC8514\n");
96
97 ptr = init_script_rev_a;
98 while (*ptr != 0xf)
99 {
100 reg_addr = *(ptr+2);
101 reg_val = *(ptr+3);
102 mask = *(ptr+4);
103 ptr+=5;
104 if (mask != 0xffff)
105 {
106 wr_masked(node, mdio_bus, phy_addr, reg_addr,reg_val,mask);
107 }
108 else
109 {
110 bdk_mdio_write(node,mdio_bus,phy_addr,reg_addr,reg_val);
111 }
112 }
113
114 BDK_TRACE(PHY,"loading init script is done\n");
115
116 }
117
vitesse_program(bdk_node_t node,int mdio_bus,int phy_addr)118 static void vitesse_program(bdk_node_t node, int mdio_bus, int phy_addr)
119 {
120 return;
121 }
122
123 /**
124 * Setup Vitesse PHYs
125 * This function sets up one port in a Vitesse VSC8514
126 */
setup_vitesse_phy(bdk_node_t node,int mdio_bus,int phy_addr)127 static void setup_vitesse_phy(bdk_node_t node, int mdio_bus, int phy_addr)
128 {
129 /*setting MAC if*/
130 bdk_mdio_write(node, mdio_bus, phy_addr, 31, VSC_PHY_GPIO_PAGE);
131 wr_masked(node,mdio_bus,phy_addr, 19, 0x4000, 0xc000);
132 bdk_mdio_write(node, mdio_bus, phy_addr, 18, 0x80e0);
133
134 /*Setting media if*/
135 bdk_mdio_write(node, mdio_bus, phy_addr, 31, VSC_PHY_STD_PAGE);
136 // Reg23, 10:8 Select copper, CAT5 copper only
137 wr_masked(node,mdio_bus,phy_addr, 23, 0x0000, 0x0700);
138
139 // Reg0:15, soft Reset
140 wr_masked(node,mdio_bus,phy_addr, 0, 0x8000, 0x8000);
141 int time_out = 100;
142 while (time_out && bdk_mdio_read(node,mdio_bus,phy_addr, 0) & 0x8000)
143 {
144 bdk_wait_usec(100000);
145 time_out--;
146 }
147
148 if (time_out == 0)
149 {
150 BDK_TRACE(PHY,"setting PHY TIME OUT\n");
151 return;
152 }
153 else
154 {
155 BDK_TRACE(PHY,"Setting a phy port is done\n");
156 }
157
158 bdk_mdio_write(node, mdio_bus, phy_addr, 31, VSC_PHY_EXT3_PAGE);
159 bdk_mdio_write(node, mdio_bus, phy_addr, 16, 0x80);
160 // Select main registers
161 bdk_mdio_write(node, mdio_bus, phy_addr, 31, VSC_PHY_STD_PAGE);
162
163 /*
164
165 if (LOOP_INTERNAL)
166 {
167 reg0 = bdk_mdio_read(node, mdio_bus, phy_addr, 0);
168 reg0 = bdk_insert(reg0, 1, 14, 1);
169 bdk_mdio_write(node, mdio_bus, phy_addr, 0, reg0);
170 }
171
172 // Far end loopback (External side)
173 if (LOOP_EXTERNAL)
174 {
175 reg23 = bdk_mdio_read(node, mdio_bus, phy_addr, 23);
176 reg23 = bdk_insert(reg23, 1, 3, 1);
177 bdk_mdio_write(node, mdio_bus, phy_addr, 23, reg23);
178 }
179
180
181 // Dump registers
182 if (false)
183 {
184 printf("\nVitesse PHY register dump, PHY address %d, mode %s\n",
185 phy_addr, (qsgmii) ? "QSGMII" : "SGMII");
186 int phy_addr = 4;
187 for (int reg_set = 0; reg_set <= 0x10; reg_set += 0x10)
188 {
189 printf("\nDump registers with reg[31]=0x%x\n", reg_set);
190 bdk_mdio_write(node, mdio_bus, phy_addr, 31, reg_set);
191 for (int reg=0; reg < 32; reg++)
192 printf("reg[%02d]=0x%x\n", reg, bdk_mdio_read(node, mdio_bus, phy_addr, reg));
193 }
194 }
195 */
196 }
197
198 //static void vetesse_setup(bdk_node_t node, int qlm, int mdio_bus, int phy_addr)
bdk_if_phy_vsc8514_setup(bdk_node_t node,int qlm,int mdio_bus,int phy_addr)199 int bdk_if_phy_vsc8514_setup(bdk_node_t node, int qlm, int mdio_bus, int phy_addr)
200 {
201 /* Check if the PHY is Vetesse PHY we expect */
202 int phy_status_1 = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID1);
203 int phy_status_2 = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID2);
204 if (phy_status_1 != 0x0007 || phy_status_2 != 0x0670)
205 {
206 bdk_error("The PHY on this board is NOT VSC8514.\n");
207 return -1;
208 }
209
210 /* Check that the GSER mode is SGMII or QSGMII */
211 bdk_qlm_modes_t qlm_mode = bdk_qlm_get_mode(node, qlm);
212 if (qlm_mode != BDK_QLM_MODE_QSGMII_4X1)
213 return -1;
214
215 vitesse_init_script(node, mdio_bus, phy_addr);
216 vitesse_program(node, mdio_bus, phy_addr);
217
218 /* VSC8514 just support QSGMII */
219 for (int port = 0; port < 4; port++)
220 setup_vitesse_phy(node, mdio_bus, phy_addr + port);
221
222 return 1;
223
224 }
225