| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386 |
- /*
- * Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include <stdio.h>
- #include <assert.h>
- #include <string.h>
- #include <stdbool.h>
- #include "cvi_eth_phy.h"
- #include "mii.h"
- // #define CVI_ETH_PHY_LOOPBACK
- #define LOOPBACK_XMII2MAC 0x8000
- #define LOOPBACK_PCS2MAC 0x2000
- #define LOOPBACK_PMA2MAC 0x1000
- #define LOOPBACK_RMII2PHY 0x0080
- #define EPHY_EFUSE_VALID_BIT_BASE 0x03050120
- #define EPHY_EFUSE_TXECHORC_FLAG 0x00000100 // bit 8
- #define EPHY_EFUSE_TXITUNE_FLAG 0x00000200 // bit 9
- #define EPHY_EFUSE_TXRXTERM_FLAG 0x00000800 // bit 11
- static inline bool phy_if_mode_is_rgmii(phy_if_mode_t interface)
- {
- return interface >= PHY_IF_MODE_RGMII && interface <= PHY_IF_MODE_RGMII_TXID;
- }
- #if defined(CVI_ETH_PHY_LOOPBACK)
- static int cv181x_set_phy_loopback(eth_phy_handle_t handle, phy_loopback_mode_t mode)
- {
- return 0;
- }
- #endif
- /**
- \brief Configure the cv181x before make it start up.
- \param[in] handle phy handle
- \return error code
- */
- /* CVITEK cv181x */
- int32_t cv181x_config(eth_phy_handle_t handle)
- {
- assert(handle);
- eth_phy_dev_t *dev = (eth_phy_dev_t *)handle;
- uint32_t val = 0;
- // eth_phy_reset(dev);
- // set rg_ephy_apb_rw_sel 0x0804@[0]=1/APB by using APB interface
- mmio_write_32(0x03009804, 0x0001);
- // Release 0x0800[0]=0/shutdown
- // mmio_write_32(0x03009800, 0x0900);
- // Release 0x0800[2]=1/dig_rst_n, Let mii_reg can be accessabile
- // mmio_write_32(0x03009800, 0x0904);
- //mdelay(10);
- // ANA INIT (PD/EN), switch to MII-page5
- mmio_write_32(0x0300907c, 0x0500);
- // Release ANA_PD p5.0x10@[13:8] = 6'b001100
- mmio_write_32(0x03009040, 0x0c00);
- // Release ANA_EN p5.0x10@[7:0] = 8'b01111110
- mmio_write_32(0x03009040, 0x0c7e);
- // Wait PLL_Lock, Lock_Status p5.0x12@[15] = 1
- //mdelay(1);
- // Release 0x0800[1] = 1/ana_rst_n
- mmio_write_32(0x03009800, 0x0906);
- // ANA INIT
- // @Switch to MII-page5
- mmio_write_32(0x0300907c, 0x0500);
- // Efuse register
- // Set Double Bias Current
- //Set rg_eth_txitune1 0x03009064 [15:8]
- //Set rg_eth_txitune0 0x03009064 [7:0]
- if ((mmio_read_32(EPHY_EFUSE_VALID_BIT_BASE) & EPHY_EFUSE_TXITUNE_FLAG) ==
- EPHY_EFUSE_TXITUNE_FLAG) {
- val = ((mmio_read_32(0x03051024) >> 24) & 0xFF) |
- (((mmio_read_32(0x03051024) >> 16) & 0xFF) << 8);
- mmio_clrsetbits_32(0x03009064, 0xFFFF, val);
- } else
- mmio_write_32(0x03009064, 0x5a5a);
- // Set Echo_I
- // Set rg_eth_txechoiadj 0x03009054 [15:8]
- if ((mmio_read_32(EPHY_EFUSE_VALID_BIT_BASE) & EPHY_EFUSE_TXECHORC_FLAG) ==
- EPHY_EFUSE_TXECHORC_FLAG) {
- mmio_clrsetbits_32(0x03009054, 0xFF00, ((mmio_read_32(0x03051024) >> 8) & 0xFF) << 8);
- } else
- mmio_write_32(0x03009054, 0x0000);
- //Set TX_Rterm & Echo_RC_Delay
- // Set rg_eth_txrterm_p1 0x03009058 [11:8]
- // Set rg_eth_txrterm 0x03009058 [7:4]
- // Set rg_eth_txechorcadj 0x03009058 [3:0]
- if ((mmio_read_32(EPHY_EFUSE_VALID_BIT_BASE) & EPHY_EFUSE_TXRXTERM_FLAG) ==
- EPHY_EFUSE_TXRXTERM_FLAG) {
- val = (((mmio_read_32(0x03051020) >> 28) & 0xF) << 4) |
- (((mmio_read_32(0x03051020) >> 24) & 0xF) << 8);
- mmio_clrsetbits_32(0x03009058, 0xFF0, val);
- } else
- mmio_write_32(0x03009058, 0x0bb0);
- // ETH_100BaseT
- // Set Rise update
- mmio_write_32(0x0300905c, 0x0c10);
- // Set Falling phase
- mmio_write_32(0x03009068, 0x0003);
- // Set Double TX Bias Current
- mmio_write_32(0x03009054, 0x0000);
- // Switch to MII-page16
- mmio_write_32(0x0300907c, 0x1000);
- // Set MLT3 Positive phase code, Set MLT3 +0
- mmio_write_32(0x03009068, 0x1000);
- mmio_write_32(0x0300906c, 0x3020);
- mmio_write_32(0x03009070, 0x5040);
- mmio_write_32(0x03009074, 0x7060);
- // Set MLT3 +I
- mmio_write_32(0x03009058, 0x1708);
- mmio_write_32(0x0300905c, 0x3827);
- mmio_write_32(0x03009060, 0x5748);
- mmio_write_32(0x03009064, 0x7867);
- // Switch to MII-page17
- mmio_write_32(0x0300907c, 0x1100);
- // Set MLT3 Negative phase code, Set MLT3 -0
- mmio_write_32(0x03009040, 0x9080);
- mmio_write_32(0x03009044, 0xb0a0);
- mmio_write_32(0x03009048, 0xd0c0);
- mmio_write_32(0x0300904c, 0xf0e0);
- // Set MLT3 -I
- mmio_write_32(0x03009050, 0x9788);
- mmio_write_32(0x03009054, 0xb8a7);
- mmio_write_32(0x03009058, 0xd7c8);
- mmio_write_32(0x0300905c, 0xf8e7);
- // @Switch to MII-page5
- mmio_write_32(0x0300907c, 0x0500);
- // En TX_Rterm
- mmio_write_32(0x03009040, (0x0001 | mmio_read_32(0x03009040)));
- // Link Pulse
- // Switch to MII-page10
- mmio_write_32(0x0300907c, 0x0a00);
- // Set Link Pulse
- mmio_write_32(0x03009040, 0x2000);
- mmio_write_32(0x03009044, 0x3832);
- mmio_write_32(0x03009048, 0x3132);
- mmio_write_32(0x0300904c, 0x2d2f);
- mmio_write_32(0x03009050, 0x2c2d);
- mmio_write_32(0x03009054, 0x1b2b);
- mmio_write_32(0x03009058, 0x94a0);
- mmio_write_32(0x0300905c, 0x8990);
- mmio_write_32(0x03009060, 0x8788);
- mmio_write_32(0x03009064, 0x8485);
- mmio_write_32(0x03009068, 0x8283);
- mmio_write_32(0x0300906c, 0x8182);
- mmio_write_32(0x03009070, 0x0081);
- // TP_IDLE
- // Switch to MII-page11
- mmio_write_32(0x0300907c, 0x0b00);
- // Set TP_IDLE
- mmio_write_32(0x03009040, 0x5252);
- mmio_write_32(0x03009044, 0x5252);
- mmio_write_32(0x03009048, 0x4B52);
- mmio_write_32(0x0300904c, 0x3D47);
- mmio_write_32(0x03009050, 0xAA99);
- mmio_write_32(0x03009054, 0x989E);
- mmio_write_32(0x03009058, 0x9395);
- mmio_write_32(0x0300905C, 0x9091);
- mmio_write_32(0x03009060, 0x8E8F);
- mmio_write_32(0x03009064, 0x8D8E);
- mmio_write_32(0x03009068, 0x8C8C);
- mmio_write_32(0x0300906C, 0x8B8B);
- mmio_write_32(0x03009070, 0x008A);
- // ETH 10BaseT Data
- // Switch to MII-page13
- mmio_write_32(0x0300907c, 0x0d00);
- mmio_write_32(0x03009040, 0x1E0A);
- mmio_write_32(0x03009044, 0x3862);
- mmio_write_32(0x03009048, 0x1E62);
- mmio_write_32(0x0300904c, 0x2A08);
- mmio_write_32(0x03009050, 0x244C);
- mmio_write_32(0x03009054, 0x1A44);
- mmio_write_32(0x03009058, 0x061C);
- // Switch to MII-page14
- mmio_write_32(0x0300907c, 0x0e00);
- mmio_write_32(0x03009040, 0x2D30);
- mmio_write_32(0x03009044, 0x3470);
- mmio_write_32(0x03009048, 0x0648);
- mmio_write_32(0x0300904c, 0x261C);
- mmio_write_32(0x03009050, 0x3160);
- mmio_write_32(0x03009054, 0x2D5E);
- // Switch to MII-page15
- mmio_write_32(0x0300907c, 0x0f00);
- mmio_write_32(0x03009040, 0x2922);
- mmio_write_32(0x03009044, 0x366E);
- mmio_write_32(0x03009048, 0x0752);
- mmio_write_32(0x0300904c, 0x2556);
- mmio_write_32(0x03009050, 0x2348);
- mmio_write_32(0x03009054, 0x0C30);
- // Switch to MII-page16
- mmio_write_32(0x0300907c, 0x1000);
- mmio_write_32(0x03009040, 0x1E08);
- mmio_write_32(0x03009044, 0x3868);
- mmio_write_32(0x03009048, 0x1462);
- mmio_write_32(0x0300904c, 0x1A0E);
- mmio_write_32(0x03009050, 0x305E);
- mmio_write_32(0x03009054, 0x2F62);
- // LED PAD MUX
- mmio_write_32(0x030010e0, 0x05);
- mmio_write_32(0x030010e4, 0x05);
- //(SD1_CLK selphy)
- mmio_write_32(0x050270b0, 0x11111111);
- //(SD1_CMD selphy)
- mmio_write_32(0x050270b4, 0x11111111);
- // LED
- // Switch to MII-page1
- mmio_write_32(0x0300907c, 0x0100);
- // select LED_LNK/SPD/DPX out to LED_PAD
- mmio_write_32(0x03009068, (mmio_read_32(0x03009068) & ~0x0f00));
- // @Switch to MII-page0
- mmio_write_32(0x0300907c, 0x0000);
- // PHY_ID
- mmio_write_32(0x03009008, 0x0043);
- mmio_write_32(0x0300900c, 0x5649);
- // Switch to MII-page19
- mmio_write_32(0x0300907c, 0x1300);
- mmio_write_32(0x03009058, 0x0012);
- // set agc max/min swing
- mmio_write_32(0x0300905C, 0x6848);
- // Switch to MII-page18
- mmio_write_32(0x0300907c, 0x1200);
- // p18.0x12, lpf
- mmio_write_32(0x03009048, 0x0808);
- mmio_write_32(0x0300904C, 0x0808);
- // hpf
- //sean
- mmio_write_32(0x03009050, 0x32f8);
- mmio_write_32(0x03009054, 0xf8dc);
- // Switch to MII-page0
- mmio_write_32(0x0300907c, 0x0000);
- // EPHY start auto-neg procedure
- mmio_write_32(0x03009800, 0x090e);
- // switch to MDIO control by ETH_MAC
- mmio_write_32(0x03009804, 0x0000);
- genphy_config(dev);
- #if defined(CVI_ETH_PHY_LOOPBACK)
- cv181x_set_phy_loopback(handle, LOOPBACK_PCS2MAC);
- #endif
- return 0;
- }
- /**
- \brief Parse 88E1xxx's speed and duplex from status register.
- \param[in] dev phy device pointer
- \return error code
- */
- static int32_t cv181x_parse_status(eth_phy_dev_t *dev)
- {
- assert(dev);
- assert(dev->priv);
- eth_phy_priv_t *priv = dev->priv;
- uint8_t phy_addr = dev->phy_addr;
- uint16_t mii_reg;
- int32_t ret;
- ret = eth_phy_read(priv, phy_addr, CVI_MII_BMSR, &mii_reg);
- if (ret != 0) {
- return ret;
- }
- if (mii_reg & (CVI_BMSR_100FULL | CVI_BMSR_100HALF))
- priv->link_info.speed = CSI_ETH_SPEED_100M;
- else
- priv->link_info.speed = CSI_ETH_SPEED_10M;
- if (mii_reg & (CVI_BMSR_10FULL | CVI_BMSR_100FULL))
- priv->link_info.duplex = CSI_ETH_DUPLEX_FULL;
- else
- priv->link_info.duplex = CSI_ETH_DUPLEX_HALF;
- return 0;
- }
- /**
- \brief Start up the 88E1111.
- \param[in] handle phy handle
- \return error code
- */
- int32_t cv181x_start(eth_phy_handle_t handle)
- {
- assert(handle);
- eth_phy_dev_t *dev = (eth_phy_dev_t *)handle;
- /* Read the Status (2x to make sure link is right) */
- genphy_update_link(dev);
- return cv181x_parse_status(dev);
- }
- /**
- \brief Halt the cv181x.
- \param[in] handle phy handle
- \return error code
- */
- int32_t cv181x_stop(eth_phy_handle_t handle)
- {
- return 0;
- }
- /**
- \brief Update the cv181x's link state.
- \param[in] handle phy handle
- \return error code
- */
- int32_t cv181x_update_link(eth_phy_handle_t handle)
- {
- assert(handle);
- eth_phy_dev_t *dev = (eth_phy_dev_t *)handle;
- return cv181x_parse_status(dev);;
- }
- /* Support for cv181x PHYs */
- eth_phy_dev_t cv181x_device = {
- .name = "CVITEK,CV181X",
- .phy_id = 0x00435649,
- .mask = 0xffffffff,
- .features = CVI_PHY_BASIC_FEATURES,
- .config = &cv181x_config,
- .start = &cv181x_start,
- .stop = &cv181x_stop,
- //.loopback = &cv181x_loopback,
- //.update_link = &cv181x_update_link,
- };
|