1 /*
2 * Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <stdio.h>
17 #include <assert.h>
18 #include <string.h>
19 #include <stdbool.h>
20
21 #include "cvi_eth_phy.h"
22 #include "mii.h"
23 #include "drv_pinmux.h"
24
25 // #define CVI_ETH_PHY_LOOPBACK
26 #define LOOPBACK_XMII2MAC 0x8000
27 #define LOOPBACK_PCS2MAC 0x2000
28 #define LOOPBACK_PMA2MAC 0x1000
29 #define LOOPBACK_RMII2PHY 0x0080
30
31 #define CVITEK_EFUSE_BASE (uintptr_t)DRV_IOREMAP((void *)0x03050000, 0x2000)
32 #define EPHY_EFUSE_VALID_BIT_BASE (CVITEK_EFUSE_BASE + 0x120)
33 #define EPHY_EFUSE_TXECHORC_FLAG 0x00000100 // bit 8
34 #define EPHY_EFUSE_TXITUNE_FLAG 0x00000200 // bit 9
35 #define EPHY_EFUSE_TXRXTERM_FLAG 0x00000800 // bit 11
36
phy_if_mode_is_rgmii(phy_if_mode_t interface)37 static inline bool phy_if_mode_is_rgmii(phy_if_mode_t interface)
38 {
39 return interface >= PHY_IF_MODE_RGMII && interface <= PHY_IF_MODE_RGMII_TXID;
40 }
41
42 #if defined(CVI_ETH_PHY_LOOPBACK)
cv181x_set_phy_loopback(eth_phy_handle_t handle,phy_loopback_mode_t mode)43 static int cv181x_set_phy_loopback(eth_phy_handle_t handle, phy_loopback_mode_t mode)
44 {
45 return 0;
46 }
47 #endif
48
49 /**
50 \brief Configure the cv181x before make it start up.
51 \param[in] handle phy handle
52 \return error code
53 */
54 /* CVITEK cv181x */
cv181x_config(eth_phy_handle_t handle)55 int32_t cv181x_config(eth_phy_handle_t handle)
56 {
57 assert(handle);
58 eth_phy_dev_t *dev = (eth_phy_dev_t *)handle;
59 uint32_t val = 0;
60
61 // eth_phy_reset(dev);
62
63 // set rg_ephy_apb_rw_sel 0x0804@[0]=1/APB by using APB interface
64 mmio_write_32(ETH_PHY_BASE + 0x804, 0x0001);
65
66 // Release 0x0800[0]=0/shutdown
67 // mmio_write_32(ETH_PHY_BASE + 0x800, 0x0900);
68
69 // Release 0x0800[2]=1/dig_rst_n, Let mii_reg can be accessabile
70 // mmio_write_32(ETH_PHY_BASE + 0x800, 0x0904);
71
72 //mdelay(10);
73
74 // ANA INIT (PD/EN), switch to MII-page5
75 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0500);
76
77 // Release ANA_PD p5.0x10@[13:8] = 6'b001100
78 mmio_write_32(ETH_PHY_BASE + 0x040, 0x0c00);
79
80 // Release ANA_EN p5.0x10@[7:0] = 8'b01111110
81 mmio_write_32(ETH_PHY_BASE + 0x040, 0x0c7e);
82
83 // Wait PLL_Lock, Lock_Status p5.0x12@[15] = 1
84 //mdelay(1);
85
86 // Release 0x0800[1] = 1/ana_rst_n
87 mmio_write_32(ETH_PHY_BASE + 0x800, 0x0906);
88
89 // ANA INIT
90 // @Switch to MII-page5
91 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0500);
92
93 // Efuse register
94 // Set Double Bias Current
95 //Set rg_eth_txitune1 0x03009064 [15:8]
96 //Set rg_eth_txitune0 0x03009064 [7:0]
97 if ((mmio_read_32(EPHY_EFUSE_VALID_BIT_BASE) & EPHY_EFUSE_TXITUNE_FLAG) == EPHY_EFUSE_TXITUNE_FLAG)
98 {
99 val = ((mmio_read_32(CVITEK_EFUSE_BASE + 0x1024) >> 24) & 0xFF) | (((mmio_read_32(CVITEK_EFUSE_BASE + 0x1024) >> 16) & 0xFF) << 8);
100 mmio_clrsetbits_32(ETH_PHY_BASE + 0x064, 0xFFFF, val);
101 }
102 else
103 mmio_write_32(ETH_PHY_BASE + 0x064, 0x5a5a);
104
105 // Set Echo_I
106 // Set rg_eth_txechoiadj 0x03009054 [15:8]
107 if ((mmio_read_32(EPHY_EFUSE_VALID_BIT_BASE) & EPHY_EFUSE_TXECHORC_FLAG) == EPHY_EFUSE_TXECHORC_FLAG)
108 {
109 mmio_clrsetbits_32(ETH_PHY_BASE + 0x054, 0xFF00, ((mmio_read_32(CVITEK_EFUSE_BASE + 0x1024) >> 8) & 0xFF) << 8);
110 }
111 else
112 mmio_write_32(ETH_PHY_BASE + 0x054, 0x0000);
113
114 //Set TX_Rterm & Echo_RC_Delay
115 // Set rg_eth_txrterm_p1 0x03009058 [11:8]
116 // Set rg_eth_txrterm 0x03009058 [7:4]
117 // Set rg_eth_txechorcadj 0x03009058 [3:0]
118 if ((mmio_read_32(EPHY_EFUSE_VALID_BIT_BASE) & EPHY_EFUSE_TXRXTERM_FLAG) == EPHY_EFUSE_TXRXTERM_FLAG)
119 {
120 val = (((mmio_read_32(CVITEK_EFUSE_BASE + 0x1020) >> 28) & 0xF) << 4) | (((mmio_read_32(CVITEK_EFUSE_BASE + 0x1020) >> 24) & 0xF) << 8);
121 mmio_clrsetbits_32(ETH_PHY_BASE + 0x058, 0xFF0, val);
122 }
123 else
124 mmio_write_32(ETH_PHY_BASE + 0x058, 0x0bb0);
125
126 // ETH_100BaseT
127 // Set Rise update
128 mmio_write_32(ETH_PHY_BASE + 0x05c, 0x0c10);
129
130 // Set Falling phase
131 mmio_write_32(ETH_PHY_BASE + 0x068, 0x0003);
132
133 // Set Double TX Bias Current
134 mmio_write_32(ETH_PHY_BASE + 0x054, 0x0000);
135
136 // Switch to MII-page16
137 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x1000);
138
139 // Set MLT3 Positive phase code, Set MLT3 +0
140 mmio_write_32(ETH_PHY_BASE + 0x068, 0x1000);
141 mmio_write_32(ETH_PHY_BASE + 0x06c, 0x3020);
142 mmio_write_32(ETH_PHY_BASE + 0x070, 0x5040);
143 mmio_write_32(ETH_PHY_BASE + 0x074, 0x7060);
144
145 // Set MLT3 +I
146 mmio_write_32(ETH_PHY_BASE + 0x058, 0x1708);
147 mmio_write_32(ETH_PHY_BASE + 0x05c, 0x3827);
148 mmio_write_32(ETH_PHY_BASE + 0x060, 0x5748);
149 mmio_write_32(ETH_PHY_BASE + 0x064, 0x7867);
150
151 // Switch to MII-page17
152 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x1100);
153
154 // Set MLT3 Negative phase code, Set MLT3 -0
155 mmio_write_32(ETH_PHY_BASE + 0x040, 0x9080);
156 mmio_write_32(ETH_PHY_BASE + 0x044, 0xb0a0);
157 mmio_write_32(ETH_PHY_BASE + 0x048, 0xd0c0);
158 mmio_write_32(ETH_PHY_BASE + 0x04c, 0xf0e0);
159
160 // Set MLT3 -I
161 mmio_write_32(ETH_PHY_BASE + 0x050, 0x9788);
162 mmio_write_32(ETH_PHY_BASE + 0x054, 0xb8a7);
163 mmio_write_32(ETH_PHY_BASE + 0x058, 0xd7c8);
164 mmio_write_32(ETH_PHY_BASE + 0x05c, 0xf8e7);
165
166 // @Switch to MII-page5
167 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0500);
168
169 // En TX_Rterm
170 mmio_write_32(ETH_PHY_BASE + 0x040, (0x0001 | mmio_read_32(ETH_PHY_BASE + 0x040)));
171
172 // Link Pulse
173 // Switch to MII-page10
174 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0a00);
175
176 // Set Link Pulse
177 mmio_write_32(ETH_PHY_BASE + 0x040, 0x2000);
178 mmio_write_32(ETH_PHY_BASE + 0x044, 0x3832);
179 mmio_write_32(ETH_PHY_BASE + 0x048, 0x3132);
180 mmio_write_32(ETH_PHY_BASE + 0x04c, 0x2d2f);
181 mmio_write_32(ETH_PHY_BASE + 0x050, 0x2c2d);
182 mmio_write_32(ETH_PHY_BASE + 0x054, 0x1b2b);
183 mmio_write_32(ETH_PHY_BASE + 0x058, 0x94a0);
184 mmio_write_32(ETH_PHY_BASE + 0x05c, 0x8990);
185 mmio_write_32(ETH_PHY_BASE + 0x060, 0x8788);
186 mmio_write_32(ETH_PHY_BASE + 0x064, 0x8485);
187 mmio_write_32(ETH_PHY_BASE + 0x068, 0x8283);
188 mmio_write_32(ETH_PHY_BASE + 0x06c, 0x8182);
189 mmio_write_32(ETH_PHY_BASE + 0x070, 0x0081);
190
191 // TP_IDLE
192 // Switch to MII-page11
193 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0b00);
194
195 // Set TP_IDLE
196 mmio_write_32(ETH_PHY_BASE + 0x040, 0x5252);
197 mmio_write_32(ETH_PHY_BASE + 0x044, 0x5252);
198 mmio_write_32(ETH_PHY_BASE + 0x048, 0x4B52);
199 mmio_write_32(ETH_PHY_BASE + 0x04c, 0x3D47);
200 mmio_write_32(ETH_PHY_BASE + 0x050, 0xAA99);
201 mmio_write_32(ETH_PHY_BASE + 0x054, 0x989E);
202 mmio_write_32(ETH_PHY_BASE + 0x058, 0x9395);
203 mmio_write_32(ETH_PHY_BASE + 0x05C, 0x9091);
204 mmio_write_32(ETH_PHY_BASE + 0x060, 0x8E8F);
205 mmio_write_32(ETH_PHY_BASE + 0x064, 0x8D8E);
206 mmio_write_32(ETH_PHY_BASE + 0x068, 0x8C8C);
207 mmio_write_32(ETH_PHY_BASE + 0x06C, 0x8B8B);
208 mmio_write_32(ETH_PHY_BASE + 0x070, 0x008A);
209
210 // ETH 10BaseT Data
211 // Switch to MII-page13
212 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0d00);
213
214 mmio_write_32(ETH_PHY_BASE + 0x040, 0x1E0A);
215 mmio_write_32(ETH_PHY_BASE + 0x044, 0x3862);
216 mmio_write_32(ETH_PHY_BASE + 0x048, 0x1E62);
217 mmio_write_32(ETH_PHY_BASE + 0x04c, 0x2A08);
218 mmio_write_32(ETH_PHY_BASE + 0x050, 0x244C);
219 mmio_write_32(ETH_PHY_BASE + 0x054, 0x1A44);
220 mmio_write_32(ETH_PHY_BASE + 0x058, 0x061C);
221
222 // Switch to MII-page14
223 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0e00);
224
225 mmio_write_32(ETH_PHY_BASE + 0x040, 0x2D30);
226 mmio_write_32(ETH_PHY_BASE + 0x044, 0x3470);
227 mmio_write_32(ETH_PHY_BASE + 0x048, 0x0648);
228 mmio_write_32(ETH_PHY_BASE + 0x04c, 0x261C);
229 mmio_write_32(ETH_PHY_BASE + 0x050, 0x3160);
230 mmio_write_32(ETH_PHY_BASE + 0x054, 0x2D5E);
231
232 // Switch to MII-page15
233 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0f00);
234
235 mmio_write_32(ETH_PHY_BASE + 0x040, 0x2922);
236 mmio_write_32(ETH_PHY_BASE + 0x044, 0x366E);
237 mmio_write_32(ETH_PHY_BASE + 0x048, 0x0752);
238 mmio_write_32(ETH_PHY_BASE + 0x04c, 0x2556);
239 mmio_write_32(ETH_PHY_BASE + 0x050, 0x2348);
240 mmio_write_32(ETH_PHY_BASE + 0x054, 0x0C30);
241
242 // Switch to MII-page16
243 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x1000);
244
245 mmio_write_32(ETH_PHY_BASE + 0x040, 0x1E08);
246 mmio_write_32(ETH_PHY_BASE + 0x044, 0x3868);
247 mmio_write_32(ETH_PHY_BASE + 0x048, 0x1462);
248 mmio_write_32(ETH_PHY_BASE + 0x04c, 0x1A0E);
249 mmio_write_32(ETH_PHY_BASE + 0x050, 0x305E);
250 mmio_write_32(ETH_PHY_BASE + 0x054, 0x2F62);
251
252 // LED PAD MUX
253 uintptr_t addr = (uintptr_t)DRV_IOREMAP((void *)0x03001000, 0x1000);
254 mmio_write_32((uintptr_t)(addr + 0xe0), 0x05);
255 mmio_write_32((uintptr_t)(addr + 0xe4), 0x05);
256
257 //(SD1_CLK selphy)
258 addr = (uintptr_t)DRV_IOREMAP((void *)0x05027000, 0x1000);
259 mmio_write_32((intptr_t)(addr + 0xb0), 0x11111111);
260 //(SD1_CMD selphy)
261 mmio_write_32((intptr_t)(addr + 0xb4), 0x11111111);
262
263 // LED
264 // Switch to MII-page1
265 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0100);
266
267 // select LED_LNK/SPD/DPX out to LED_PAD
268 mmio_write_32(ETH_PHY_BASE + 0x068, (mmio_read_32(ETH_PHY_BASE + 0x068) & ~0x0f00));
269
270 // @Switch to MII-page0
271 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0000);
272
273 // PHY_ID
274 mmio_write_32(ETH_PHY_BASE + 0x008, 0x0043);
275 mmio_write_32(ETH_PHY_BASE + 0x00c, 0x5649);
276
277 // Switch to MII-page19
278 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x1300);
279 mmio_write_32(ETH_PHY_BASE + 0x058, 0x0012);
280 // set agc max/min swing
281 mmio_write_32(ETH_PHY_BASE + 0x05C, 0x6848);
282
283 // Switch to MII-page18
284 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x1200);
285 // p18.0x12, lpf
286 mmio_write_32(ETH_PHY_BASE + 0x048, 0x0808);
287 mmio_write_32(ETH_PHY_BASE + 0x04C, 0x0808);
288 // hpf
289 //sean
290 mmio_write_32(ETH_PHY_BASE + 0x050, 0x32f8);
291 mmio_write_32(ETH_PHY_BASE + 0x054, 0xf8dc);
292
293 // Switch to MII-page0
294 mmio_write_32(ETH_PHY_BASE + 0x07c, 0x0000);
295 // EPHY start auto-neg procedure
296 mmio_write_32(ETH_PHY_BASE + 0x800, 0x090e);
297
298 // switch to MDIO control by ETH_MAC
299 mmio_write_32(ETH_PHY_BASE + 0x804, 0x0000);
300
301 genphy_config(dev);
302
303 #if defined(CVI_ETH_PHY_LOOPBACK)
304 cv181x_set_phy_loopback(handle, LOOPBACK_PCS2MAC);
305 #endif
306
307 return 0;
308 }
309
310 /**
311 \brief Parse 88E1xxx's speed and duplex from status register.
312 \param[in] dev phy device pointer
313 \return error code
314 */
cv181x_parse_status(eth_phy_dev_t * dev)315 static int32_t cv181x_parse_status(eth_phy_dev_t *dev)
316 {
317 assert(dev);
318 assert(dev->priv);
319 eth_phy_priv_t *priv = dev->priv;
320 uint8_t phy_addr = dev->phy_addr;
321 uint16_t mii_reg;
322 int32_t ret;
323
324 ret = eth_phy_read(priv, phy_addr, CVI_MII_BMSR, &mii_reg);
325
326 if (ret != 0) {
327 return ret;
328 }
329
330 if (mii_reg & (CVI_BMSR_100FULL | CVI_BMSR_100HALF))
331 priv->link_info.speed = CSI_ETH_SPEED_100M;
332 else
333 priv->link_info.speed = CSI_ETH_SPEED_10M;
334
335 if (mii_reg & (CVI_BMSR_10FULL | CVI_BMSR_100FULL))
336 priv->link_info.duplex = CSI_ETH_DUPLEX_FULL;
337 else
338 priv->link_info.duplex = CSI_ETH_DUPLEX_HALF;
339
340 return 0;
341 }
342
343 /**
344 \brief Start up the 88E1111.
345 \param[in] handle phy handle
346 \return error code
347 */
cv181x_start(eth_phy_handle_t handle)348 int32_t cv181x_start(eth_phy_handle_t handle)
349 {
350 assert(handle);
351
352 eth_phy_dev_t *dev = (eth_phy_dev_t *)handle;
353
354 /* Read the Status (2x to make sure link is right) */
355 genphy_update_link(dev);
356
357 return cv181x_parse_status(dev);
358 }
359
360 /**
361 \brief Halt the cv181x.
362 \param[in] handle phy handle
363 \return error code
364 */
cv181x_stop(eth_phy_handle_t handle)365 int32_t cv181x_stop(eth_phy_handle_t handle)
366 {
367 return 0;
368 }
369
370 /**
371 \brief Update the cv181x's link state.
372 \param[in] handle phy handle
373 \return error code
374 */
cv181x_update_link(eth_phy_handle_t handle)375 int32_t cv181x_update_link(eth_phy_handle_t handle)
376 {
377 assert(handle);
378 eth_phy_dev_t *dev = (eth_phy_dev_t *)handle;
379 return cv181x_parse_status(dev);;
380 }
381
382
383 /* Support for cv181x PHYs */
384 eth_phy_dev_t cv181x_device = {
385 .name = "CVITEK,CV181X",
386 .phy_id = 0x00435649,
387 .mask = 0xffffffff,
388 .features = CVI_PHY_BASIC_FEATURES,
389 .config = &cv181x_config,
390 .start = &cv181x_start,
391 .stop = &cv181x_stop,
392 //.loopback = &cv181x_loopback,
393 //.update_link = &cv181x_update_link,
394 };
395