xref: /aosp_15_r20/external/coreboot/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse-8514.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
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