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