⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 phydrv.c

📁 Vitesse 24port gigabit Switch Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
/*

    Copyright (c) 2002-2006 Vitesse Semiconductor Corporation "Vitesse".  
    All Rights Reserved.  Unpublished rights reserved under the copyright laws
    of the United States of America, other countries and international treaties.
    The software is provided without a fee. Permission to use, copy, store and 
    modify, the software and its source code is granted. Permission to integrate
    into other products, disclose, transmit and distribute the software in an
    absolute machine readable format (e.g. HEX file) is also granted. 

    The source code of the software may not be disclosed, transmitted or
    distributed without the written permission of Vitesse. The software and its
    source code may only be used in products utilizing a Vitesse VSC73xx product.
 
    This copyright notice must appear in any copy, modification, disclosure,
    transmission or distribution of the software. Vitesse retains all ownership,
    copyright, trade secret and proprietary rights in the software.  

    THIS SOFTWARE HAS BEEN PROVIDED "AS IS," WITHOUT EXPRESS OR IMPLIED WARRANTY
    INCLUDING, WITHOUT LIMITATION, IMPLIED WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR USE AND NON-INFRINGEMENT.

*/
#include "common.h"
#include "h2reg.h"
#include "h2io.h"
#include "h2aux.h"
#include "hwconf.h"
#include "phyconf.h"
#include "phydrv.h"
#include "phytsk.h"
#include "phymap.h"
#include "timer.h"
#include "main.h"
#include "misc2.h"
#include "print.h"
#include "swconf.h"


/* ************************************************************************ **
 *
 *
 * Defines
 *
 *
 *
 * ************************************************************************ */

/* Special page registers */
#define TP_PAGE_CODE 0x2a30
#define TR_PAGE_CODE 0x52b5

/* define bit masks for read/write MIIM.  NOTE, offset by 16 bit*/
#define MIIM_CMD_READ                     0x0400
#define MIIM_CMD_WRITE                    0x0000

/* define bit masks for MIIM data register */
#define MIIM_DATA_FAILURE_MASK            0x00010000

/* define bit masks for MIIM command register */
#define MIIM_COMPLETED_MASK               0x0000000B

/* ************************************************************************ **
 *
 *
 * Typedefs and enums
 *
 *
 *
 * ************************************************************************ */


/* ************************************************************************ **
 *
 *
 * Prototypes for local functions
 *
 *
 *
 * ************************************************************************ */

static void phy_await_completed (uchar miim_no) small;
static void phy_receiver_init (uchar port_no);
static void phy_receiver_reconfig (uchar port_no);
static void sgmii_tr_await_completed (void);
#if SFP_NUM
static void phy_sfp_init (uchar port_no);
#endif
static void assert_reset (uchar port_no);

/* ************************************************************************ **
 *
 *
 * Local data
 *
 *
 *
 * ************************************************************************ */

#if SFP_NUM
code uchar sfp_ports               [SFP_NUM] = SFP_PORTS;
code uchar sfp_module_detect_gpios [SFP_NUM] = SFP_MODULE_DETECT_GPIOS;
code uchar sfp_tx_disable_gpios    [SFP_NUM] = SFP_TX_DISABLE_GPIOS;

static uchar sfp_module_detect_status = 0; /* Each SFP represented by a bit */
#endif

/* ************************************************************************ **
 *
 *
 * PHY initialization sequences
 *
 *
 *
 * ************************************************************************ */

#define VTSS_INTERNAL_PHY 1

#if VTSS_8538 || VTSS_INTERNAL_PHY
void init_seq_common_1 (uchar port_no)
{
    phy_page_tp(port_no);
    phy_write_masked(port_no, 8, 0x0200, 0x0200);

    phy_page_tr(port_no);

    phy_write(port_no, 16, 0xaf8a);
    phy_write_masked(port_no, 17, 0x0008, 0x000c);
    phy_write(port_no, 16, 0x8f8a);

    phy_write(port_no, 16, 0xaf86);
    phy_write_masked(port_no, 18, 0x0008, 0x000c);
    phy_write(port_no, 16, 0x8f86);

    phy_write(port_no, 16, 0xaf82);
    phy_write_masked(port_no, 17, 0x0100, 0x0180);
    phy_write(port_no, 16, 0x8f82);

    phy_page_tp(port_no);
    phy_write_masked(port_no, 8, 0x0000, 0x0200);

    phy_page_std(port_no);
}
#endif

void init_seq_common_2 (uchar port_no)
{
    phy_page_tp(port_no);
    phy_write_masked(port_no, 8, 0x200, 0x200);
    phy_page_tr(port_no);
    phy_write(port_no, 16, 0xb68a);
    phy_write_masked(port_no, 18, 0x0003, 0xff07);
    phy_write_masked(port_no, 17, 0x00a2, 0x00ff); 
    phy_write(port_no, 16, 0x968a);
    phy_page_tp(port_no);
    phy_write_masked(port_no, 8, 0x0000, 0x0200);
    phy_page_std(port_no);
}


/*
** Initialization sequence for internal PHYs on VSC7390
*/
void init_seq_7390 (uchar port_no)
{    
    init_seq_common_1(port_no);
    init_seq_common_2(port_no);


    phy_write_masked(port_no, 24, 0xa002, 0xe00e);

    phy_write_masked(port_no, 18, 0x0040, 0x0040);
}

void sgmii_lock_seq(uchar port_no)
{
    if ((port_no < 8) || (port_no > 15)) {
        uchar rx_tr_lock;

        (void) sgmii_tr_read(port_no, 6);
        rx_tr_lock = (sgmii_tr_read(port_no, 6) >> 3) & 0x01;
        if (!rx_tr_lock) {
            sgmii_tr_write(port_no, 2, 0x10);
            sgmii_tr_write(port_no, 0, 0xdf);
            sgmii_tr_write(port_no, 0, 0xff);
            sgmii_tr_write(port_no, 2, 0x00);
            (void) sgmii_tr_read(port_no, 6);
            rx_tr_lock = (sgmii_tr_read(port_no, 6) >> 3) & 0x01;
            if (!rx_tr_lock) {
            }            
        }
    }
}

#if VTSS_8224
/*
** Initialization sequence for 8224/8244 PHYs
*/
void init_seq_8224 (uchar port_no)
{
    phy_page_tp(port_no);
    phy_write(port_no,  8, 0x0212);
    phy_page_tr(port_no);
    phy_write(port_no, 16, 0xafa4);
    phy_write(port_no, 18, 0x000f);
    phy_write(port_no, 17, 0x492a);
    phy_write(port_no, 16, 0x8fa4);
    phy_page_tp(port_no);
    phy_write(port_no,  8, 0x0012);
    phy_page_tp(port_no);
    phy_write(port_no,  8, 0x0212);
    phy_page_tr(port_no);
    phy_write(port_no, 18, 0x0004);
    phy_write(port_no, 17, 0x0671);
    phy_write(port_no, 16, 0x8fae);
    phy_page_tp(port_no);
    phy_write(port_no,  8, 0x0012);
    phy_page_std(port_no);
    phy_write(port_no, 18, 0x0049);
    phy_page_tp(port_no);
    phy_write(port_no,  3, 0xf082);
    phy_write(port_no,  3, 0xf082);
    phy_page_std(port_no);
}
#endif

#if VTSS_8538

void phy_immediate_init_seq_8538 (uchar port_no)
{
    ushort reg_3;

    /* This sequence should only be applied to revision A. As this function is only 
    ** called if PHY register 2 reads 0007h, we only need to read register 3 to
    ** determine the model and revision number.
    */
    reg_3 = phy_read(port_no, 3);
    if ((reg_3 == ((ushort) PHY_ID_VTSS_8538_A)) || (reg_3 == ((ushort) PHY_ID_VTSS_8558_A))) {
        phy_write(port_no, 31, 0x0010);
        phy_write(port_no,  0, 0x4c19);
        phy_write_masked(port_no, 0, 0x8000, 0x8000);
        phy_write(port_no, 31, 0x0000);
    }
}


/*
** Initialization sequence for 8538/8558 PHYs
*/
static void init_seq_8538 (uchar port_no, uchar revision)
{

    init_seq_common_1(port_no);

    if (revision == 0) {
        phy_page_tr(port_no);
        phy_write(port_no, 18, 0x0000);
        phy_write(port_no, 17, 0x003d);
        phy_write(port_no, 16, 0x8606);
        phy_write(port_no, 18, 0x0000);
        phy_write(port_no, 17, 0x003d);
        phy_write(port_no, 16, 0x8e06);
        phy_page_std(port_no);


        phy_page_tp(port_no);
        phy_write_masked(port_no, 27, 0x8000, 0x8000);
        phy_write_masked(port_no, 19, 0x0300, 0x0f00);
        phy_page_std(port_no);

        phy_page_ext(port_no);
        phy_write_masked(port_no, 17, 0x0000, 0x0001);
        phy_page_std(port_no);

        if ((port_no == 0) || (port_no == 8) || (port_no == 16)) {
            phy_write(port_no, 31, 0x10);

            phy_write(port_no,  0, 0x7009);
            phy_write(port_no, 12, 0x5000);
            phy_write(port_no, 11, 0xffff);
            phy_write(port_no, 12, 0x5002);
            phy_write(port_no, 12, 0x5040);
            phy_write(port_no, 12, 0x500C);
            phy_write(port_no, 12, 0x5002);
            phy_write(port_no, 12, 0x5040);
            phy_write(port_no, 12, 0x5021);
            phy_write(port_no, 12, 0x5002);
            phy_write(port_no, 12, 0x5040);
            phy_write(port_no, 12, 0x5022);
            phy_write(port_no, 12, 0x5002);
            phy_write(port_no, 12, 0x5040);
            phy_write(port_no, 12, 0x5023);
            phy_write(port_no, 12, 0x50C2);
            phy_write(port_no, 12, 0x50AD);
            phy_write(port_no, 12, 0x50C2);
            phy_write(port_no, 12, 0x50CA);
            phy_write(port_no, 12, 0x5075);
            phy_write(port_no, 12, 0x50CB);
            phy_write(port_no, 12, 0x509A);
            phy_write(port_no, 12, 0x5075);
            phy_write(port_no, 12, 0x50CA);
            phy_write(port_no, 12, 0x5046);
            phy_write(port_no, 12, 0x5085);
            phy_write(port_no, 12, 0x50CB);
            phy_write(port_no, 12, 0x50CD);
            phy_write(port_no, 12, 0x5085);
            phy_write(port_no, 12, 0x50CA);
            phy_write(port_no, 12, 0x50CC);
            phy_write(port_no, 12, 0x50D2);
            phy_write(port_no, 12, 0x50CA);
            phy_write(port_no, 12, 0x50D2);
            phy_write(port_no, 12, 0x50AD);
            phy_write(port_no, 12, 0x5022);
            phy_write(port_no, 12, 0x5022);
            phy_write(port_no, 12, 0x5022);
            phy_write(port_no, 12, 0x5022);
            phy_write(port_no, 12, 0x0000);
            phy_write(port_no,  0, 0x4099);
            phy_write(port_no,  0, 0xc099);
        }
    }

    phy_page_std(port_no);


    phy_write_masked(port_no, 18, 0x0040, 0x0040);

    /* 100M edge rate and transmitter amplitude control */
    phy_write_masked(port_no, 24, 0xa002, 0xe00e);

}
#endif


/* ************************************************************************ */
void phy_post_reset (uchar port_no)
/* ------------------------------------------------------------------------ --
 * Purpose     : Do the necessary hardware configuration of a PHY after it
 *               has been reset.
 * Remarks     :
 * Restrictions:
 * See also    :
 * Example     :
 * ************************************************************************ */
{
    phy_id_t phy_id;



    /* Read PHY id to determine action */
    phy_read_id(port_no, &phy_id);

    switch (phy_id.family) {

    case PHY_FAMILY_VTSS_7390:
        init_seq_7390(port_no);
        phy_receiver_init(port_no);
        phy_write(port_no, 27, PHY_LED_MODE);
        break;

#if VTSS_8538
    case PHY_FAMILY_VTSS_8538:
        if (phy_id.model == PHY_MODEL_VTSS_8558) {

#if SFP_NUM
            if (PORT_BIT_MASK(port_no) & SFP_PORT_MASK) {
                phy_sfp_init(port_no);
            }
#endif

        }
        init_seq_8538(port_no, phy_id.revision);
        phy_receiver_init(port_no);
        phy_write(port_no, 29, PHY_LED_MODE);
        /* set LED to blink with 5 Hz */
        phy_write_masked(port_no, 30, 0x0400, 0x0600);
        phy_write_masked(port_no, 30, 0x0000, 0x000f);
        break;
#endif

#if VTSS_8224
    case PHY_FAMILY_VTSS_8224:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -