GigaDevice_test/PHY/PHY_DP83848C.c

306 lines
7.6 KiB
C

/*
* Copyright (c) 2013-2018 Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* 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
*
* 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.
*
* -----------------------------------------------------------------------
*
* $Date: 25. May 2018
* $Revision: V6.2
*
* Driver: Driver_ETH_PHYn (default: Driver_ETH_PHY0)
* Project: Ethernet Physical Layer Transceiver (PHY)
* Driver for DP83848C
* -----------------------------------------------------------------------
* Use the following configuration settings in the middleware component
* to connect to this driver.
*
* Configuration Setting Value
* --------------------- -----
* Connect to hardware via Driver_ETH_PHY# = n (default: 0)
* -------------------------------------------------------------------- */
/* History:
* Version 6.2
* Updated for ARM compiler 6
* Version 6.1
* Added driver flow control flags
* Version 6.0
* Based on API V2.00
* Version 5.1
* Based on API V1.10 (namespace prefix ARM_ added)
* Version 5.0
* Initial release
*/
#include "PHY_DP83848C.h"
#define ARM_ETH_PHY_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(6,2) /* driver version */
#ifndef ETH_PHY_NUM
#define ETH_PHY_NUM 0 /* Default driver number */
#endif
#ifndef ETH_PHY_ADDR
#define ETH_PHY_ADDR 0x01 /* Default device address */
#endif
/* Driver Version */
static const ARM_DRIVER_VERSION DriverVersion = {
ARM_ETH_PHY_API_VERSION,
ARM_ETH_PHY_DRV_VERSION
};
/* Ethernet PHY control structure */
static PHY_CTRL PHY = { NULL, NULL, 0, 0, 0 };
/**
\fn ARM_DRIVER_VERSION GetVersion (void)
\brief Get driver version.
\return \ref ARM_DRIVER_VERSION
*/
static ARM_DRIVER_VERSION GetVersion (void) {
return DriverVersion;
}
/**
\fn int32_t Initialize (ARM_ETH_PHY_Read_t fn_read,
ARM_ETH_PHY_Write_t fn_write)
\brief Initialize Ethernet PHY Device.
\param[in] fn_read Pointer to \ref ARM_ETH_MAC_PHY_Read
\param[in] fn_write Pointer to \ref ARM_ETH_MAC_PHY_Write
\return \ref execution_status
*/
static int32_t Initialize (ARM_ETH_PHY_Read_t fn_read, ARM_ETH_PHY_Write_t fn_write) {
if ((fn_read == NULL) || (fn_write == NULL)) { return ARM_DRIVER_ERROR_PARAMETER; }
if ((PHY.flags & PHY_INIT) == 0U) {
/* Register PHY read/write functions. */
PHY.reg_rd = fn_read;
PHY.reg_wr = fn_write;
PHY.bmcr = 0U;
PHY.flags = PHY_INIT;
}
return ARM_DRIVER_OK;
}
/**
\fn int32_t Uninitialize (void)
\brief De-initialize Ethernet PHY Device.
\return \ref execution_status
*/
static int32_t Uninitialize (void) {
PHY.reg_rd = NULL;
PHY.reg_wr = NULL;
PHY.bmcr = 0U;
PHY.flags = 0U;
return ARM_DRIVER_OK;
}
/**
\fn int32_t PowerControl (ARM_POWER_STATE state)
\brief Control Ethernet PHY Device Power.
\param[in] state Power state
\return \ref execution_status
*/
static int32_t PowerControl (ARM_POWER_STATE state) {
uint16_t val;
switch ((int32_t)state) {
case ARM_POWER_OFF:
if ((PHY.flags & PHY_INIT) == 0U) {
/* Initialize must provide register access function pointers */
return ARM_DRIVER_ERROR;
}
PHY.flags &= ~PHY_POWER;
PHY.bmcr = BMCR_POWER_DOWN;
return (PHY.reg_wr(ETH_PHY_ADDR, REG_BMCR, PHY.bmcr));
case ARM_POWER_FULL:
if ((PHY.flags & PHY_INIT) == 0U) {
return ARM_DRIVER_ERROR;
}
if (PHY.flags & PHY_POWER) {
return ARM_DRIVER_OK;
}
/* Check Device Identification. */
PHY.reg_rd(ETH_PHY_ADDR, REG_PHYIDR1, &val);
if (val != PHY_ID1) {
/* Invalid PHY ID */
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
PHY.reg_rd(ETH_PHY_ADDR, REG_PHYIDR2, &val);
if ((val & 0xFFF0) != PHY_ID2) {
/* Invalid PHY ID */
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
PHY.bmcr = 0U;
if (PHY.reg_wr(ETH_PHY_ADDR, REG_BMCR, PHY.bmcr) != ARM_DRIVER_OK) {
return ARM_DRIVER_ERROR;
}
PHY.flags |= PHY_POWER;
return ARM_DRIVER_OK;
case ARM_POWER_LOW:
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
}
/**
\fn int32_t SetInterface (uint32_t interface)
\brief Set Ethernet Media Interface.
\param[in] interface Media Interface type
\return \ref execution_status
*/
static int32_t SetInterface (uint32_t interface) {
uint16_t val;
if ((PHY.flags & PHY_POWER) == 0U) { return ARM_DRIVER_ERROR; }
switch (interface) {
case ARM_ETH_INTERFACE_MII:
val = 0x0001;
break;
case ARM_ETH_INTERFACE_RMII:
val = RBR_RMII_MODE | 0x0001;
break;
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
return (PHY.reg_wr(ETH_PHY_ADDR, REG_RBR, val));
}
/**
\fn int32_t SetMode (uint32_t mode)
\brief Set Ethernet PHY Device Operation mode.
\param[in] mode Operation Mode
\return \ref execution_status
*/
static int32_t SetMode (uint32_t mode) {
uint16_t val;
if ((PHY.flags & PHY_POWER) == 0U) { return ARM_DRIVER_ERROR; }
val = PHY.bmcr & BMCR_POWER_DOWN;
switch (mode & ARM_ETH_PHY_SPEED_Msk) {
case ARM_ETH_PHY_SPEED_10M:
break;
case ARM_ETH_PHY_SPEED_100M:
val |= BMCR_SPEED_SEL;
break;
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
switch (mode & ARM_ETH_PHY_DUPLEX_Msk) {
case ARM_ETH_PHY_DUPLEX_HALF:
break;
case ARM_ETH_PHY_DUPLEX_FULL:
val |= BMCR_DUPLEX;
break;
default:
return ARM_DRIVER_ERROR_UNSUPPORTED;
}
if (mode & ARM_ETH_PHY_AUTO_NEGOTIATE) {
val |= BMCR_ANEG_EN;
}
if (mode & ARM_ETH_PHY_LOOPBACK) {
val |= BMCR_LOOPBACK;
}
if (mode & ARM_ETH_PHY_ISOLATE) {
val |= BMCR_ISOLATE;
}
PHY.bmcr = val;
return (PHY.reg_wr(ETH_PHY_ADDR, REG_BMCR, PHY.bmcr));
}
/**
\fn ARM_ETH_LINK_STATE GetLinkState (void)
\brief Get Ethernet PHY Device Link state.
\return current link status \ref ARM_ETH_LINK_STATE
*/
static ARM_ETH_LINK_STATE GetLinkState (void) {
ARM_ETH_LINK_STATE state;
uint16_t val = 0U;
if (PHY.flags & PHY_POWER) {
PHY.reg_rd(ETH_PHY_ADDR, REG_BMSR, &val);
}
state = (val & BMSR_LINK_STAT) ? ARM_ETH_LINK_UP : ARM_ETH_LINK_DOWN;
return (state);
}
/**
\fn ARM_ETH_LINK_INFO GetLinkInfo (void)
\brief Get Ethernet PHY Device Link information.
\return current link parameters \ref ARM_ETH_LINK_INFO
*/
static ARM_ETH_LINK_INFO GetLinkInfo (void) {
ARM_ETH_LINK_INFO info;
uint16_t val = 0U;
if (PHY.flags & PHY_POWER) {
PHY.reg_rd(ETH_PHY_ADDR, REG_PHYSTS, &val);
}
info.speed = (val & PHYSTS_SPEED) ? ARM_ETH_SPEED_10M : ARM_ETH_SPEED_100M;
info.duplex = (val & PHYSTS_DUPLEX) ? ARM_ETH_DUPLEX_FULL : ARM_ETH_DUPLEX_HALF;
return (info);
}
/* PHY Driver Control Block */
extern
ARM_DRIVER_ETH_PHY ARM_Driver_ETH_PHY_(ETH_PHY_NUM);
ARM_DRIVER_ETH_PHY ARM_Driver_ETH_PHY_(ETH_PHY_NUM) = {
GetVersion,
Initialize,
Uninitialize,
PowerControl,
SetInterface,
SetMode,
GetLinkState,
GetLinkInfo
};