rt-thread/bsp/phytium/libraries/standalone/drivers/eth/fxmac/fxmac_options.c

767 lines
28 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright : (C) 2022 Phytium Information Technology, Inc.
* All Rights Reserved.
*
* This program is OPEN SOURCE software: you can redistribute it and/or modify it
* under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
* either version 1.0 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the Phytium Public License for more details.
*
*
* FilePath: fxmac_options.c
* Date: 2022-04-06 14:46:52
* LastEditTime: 2022-04-06 14:46:58
* Description:  This file is for options functions
*
* Modify History:
* Ver   Who        Date         Changes
* ----- ------     --------    --------------------------------------
* 1.0 huanghe 2022/06/16 first release
* 1.1 liuzhihong 2023/4/11 jumbo support
*/
#include "fxmac_hw.h"
#include "fxmac.h"
#include "fassert.h"
#include "ftypes.h"
/**
* @name: FXmacSetMacAddress
*
* @msg: Set the MAC address for this driver/device. The address is a 48-bit value.
* The device must be stopped before calling this function.
*
* @param {FXmac *}: instance_p is a pointer to the instance to be worked on.
* @param address_ptr is a pointer to a 6-byte MAC address.
* @param index plus 1 is a index to which MAC (1-4) address.
*
* @return
* - FT_SUCCESS if the MAC address was set successfully
* - FXMAC_ERR_MAC_IS_PROCESSING if the device has not yet been stopped
*
*/
FError FXmacSetMacAddress(FXmac *instance_p, u8 *address_ptr, u8 index)
{
u32 mac_addr;
u8 *aptr = (u8 *)(void *)address_ptr;
u8 index_loc = index;
FError status;
FASSERT(instance_p != NULL);
FASSERT(aptr != NULL);
FASSERT(instance_p->is_ready == (u32)FT_COMPONENT_IS_READY);
FASSERT((index_loc < (u8)FXMAC_MAX_MAC_ADDR));
/* Be sure device has been stopped */
if (instance_p->is_started == (u32)FT_COMPONENT_IS_STARTED)
{
status = (FError)(FXMAC_ERR_MAC_IS_PROCESSING);
}
else
{
/* Set the MAC bits [31:0] in BOT */
mac_addr = *(aptr);
mac_addr |= ((u32)(*(aptr + 1)) << 8U);
mac_addr |= ((u32)(*(aptr + 2)) << 16U);
mac_addr |= ((u32)(*(aptr + 3)) << 24U);
FXMAC_WRITEREG32(instance_p->config.base_address,
((u32)FXMAC_GEM_SA1B + ((u32)index_loc * (u32)8)), mac_addr);
/* There are reserved bits in TOP so don't affect them */
mac_addr = FXMAC_READREG32(instance_p->config.base_address,
((u32)FXMAC_GEM_SA1T + ((u32)index_loc * (u32)8)));
mac_addr &= (u32)(~FXMAC_GEM_SAB_MASK);
/* Set MAC bits [47:32] in TOP */
mac_addr |= (u32)(*(aptr + 4));
mac_addr |= (u32)(*(aptr + 5)) << 8U;
FXMAC_WRITEREG32(instance_p->config.base_address,
((u32)FXMAC_GEM_SA1T + ((u32)index_loc * (u32)8)), mac_addr);
status = (FError)(FT_SUCCESS);
}
return status;
}
/**
* @name: FXmacGetMacAddress
* @msg: Set the MAC address according to index
* @param {FXmac} *mac is a pointer to the instance to be worked on.
* @param {void} *address_ptr is an output parameter, and is a pointer to a buffer into
* which the current MAC address will be copied.
* @param {u8} index is a index to which MAC (0-3) address.
*/
void FXmacGetMacAddress(FXmac *instance_p, u8 *address_ptr, u8 index)
{
u32 reg_value;
u8 *ptr = (u8 *)address_ptr;
FASSERT(instance_p != NULL);
FASSERT(ptr != NULL);
FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
FASSERT((index < FXMAC_MAX_MAC_ADDR));
reg_value = FXMAC_READREG32(instance_p->config.base_address, FXMAC_GEM_SA1B + ((u32)index * (u32)8));
*ptr = (u8)reg_value;
*(ptr + 1) = (u8)(reg_value >> 8U);
*(ptr + 2) = (u8)(reg_value >> 16U);
*(ptr + 3) = (u8)(reg_value >> 24U);
reg_value = FXMAC_READREG32(instance_p->config.base_address, FXMAC_GEM_SA1T + ((u32)index * (u32)8));
*(ptr + 4) = (u8)(reg_value);
*(ptr + 5) = (u8)(reg_value >> 8U);
}
/**
* Set the Type ID match for this driver/device. The register is a 32-bit
* value. The device must be stopped before calling this function.
*
* @param instance_p is a pointer to the instance to be worked on.
* @param id_check is type ID to be configured.
* @param index plus 1 is a index to which Type ID (1-4).
*
* @return
* - FT_SUCCESS if the MAC address was set successfully
* - FXMAC_ERR_MAC_IS_PROCESSING if the device has not yet been stopped
*
*/
FError FXmacSetTypeIdCheck(FXmac *instance_p, u32 id_check, u8 index)
{
u8 index_loc = index;
FError status;
FASSERT(instance_p != NULL);
FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
FASSERT((index_loc < (u8)FXMAC_MAX_TYPE_ID));
/* Be sure device has been stopped */
if (instance_p->is_started == (u32)FT_COMPONENT_IS_STARTED)
{
status = (FError)(FXMAC_ERR_MAC_IS_PROCESSING);
}
else
{
/* Set the ID bits in MATCHx register */
FXMAC_WRITEREG32(instance_p->config.base_address,
((u32)FXMAC_MATCH1_OFFSET + ((u32)index_loc * (u32)4)), id_check);
status = (FError)(FT_SUCCESS);
}
return status;
}
/**
* Set options for the driver/device. The driver should be stopped with
* FXmacStop() before changing options.
*
* @param instance_p is a pointer to the instance to be worked on.
* @param options are the options to set. Multiple options can be set by OR'ing
* FXMAC_*_OPTIONS constants together. options not specified are not
* affected.
* @param queue_num is the Buffer Queue Index ,Used for jumbo frames only
*
* @return
* - FT_SUCCESS if the options were set successfully
* - FXMAC_ERR_MAC_IS_PROCESSING if the device has not yet been stopped
*
* @note
* See fxmac.h for a description of the available options.
*
*/
FError FXmacSetOptions(FXmac *instance_p, u32 options, u32 queue_num)
{
u32 reg; /* Generic register contents */
u32 reg_netcfg; /* Reflects original contents of NET_CONFIG */
u32 reg_new_netcfg; /* Reflects new contents of NET_CONFIG */
FError status;
FXmacConfig *config_p;
FASSERT(instance_p != NULL);
FASSERT(instance_p->is_ready == (u32)FT_COMPONENT_IS_READY);
config_p = &instance_p->config;
/* Be sure device has been stopped */
if (instance_p->is_started == (u32)FT_COMPONENT_IS_STARTED)
{
status = (FError)(FXMAC_ERR_MAC_IS_PROCESSING);
}
else
{
/* Many of these options will change the NET_CONFIG registers.
* To reduce the amount of IO to the device, group these options here
* and change them all at once.
*/
/* Grab current register contents */
reg_netcfg = FXMAC_READREG32(config_p->base_address,
FXMAC_NWCFG_OFFSET);
reg_new_netcfg = reg_netcfg;
/*
* It is configured to max 1536.
*/
if ((options & FXMAC_FRAME1536_OPTION) != 0x00000000U)
{
reg_new_netcfg |= (FXMAC_NWCFG_1536RXEN_MASK);
}
/* Turn on VLAN packet only, only VLAN tagged will be accepted */
if ((options & FXMAC_VLAN_OPTION) != 0x00000000U)
{
reg_new_netcfg |= FXMAC_NWCFG_NVLANDISC_MASK;
}
/* Turn on FCS stripping on receive packets */
if ((options & FXMAC_FCS_STRIP_OPTION) != 0x00000000U)
{
reg_new_netcfg |= FXMAC_NWCFG_FCS_REMOVE_MASK;
}
/* Turn on length/type field checking on receive packets */
if ((options & FXMAC_LENTYPE_ERR_OPTION) != 0x00000000U)
{
reg_new_netcfg |= FXMAC_NWCFG_LENGTH_FIELD_ERROR_FRAME_DISCARD_MASK;
}
/* Turn on flow control */
if ((options & FXMAC_FLOW_CONTROL_OPTION) != 0x00000000U)
{
reg_new_netcfg |= FXMAC_NWCFG_PAUSE_ENABLE_MASK;
}
/* Turn on promiscuous frame filtering (all frames are received) */
if ((options & FXMAC_PROMISC_OPTION) != 0x00000000U)
{
reg_new_netcfg |= FXMAC_NWCFG_COPYALLEN_MASK;
}
/* Allow broadcast address reception */
if ((options & FXMAC_BROADCAST_OPTION) != 0x00000000U)
{
reg_new_netcfg &= (u32)(~FXMAC_NWCFG_BCASTDI_MASK);
}
/* Allow multicast address filtering */
if ((options & FXMAC_MULTICAST_OPTION) != 0x00000000U)
{
reg_new_netcfg |= FXMAC_NWCFG_MCASTHASHEN_MASK;
}
/* enable RX checksum offload */
if ((options & FXMAC_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U)
{
reg_new_netcfg |= FXMAC_NWCFG_RXCHKSUMEN_MASK;
}
/* Enable jumbo frames */
if ((options & FXMAC_JUMBO_ENABLE_OPTION) != 0x00000000U)
{
instance_p->max_mtu_size = FXMAC_MTU_JUMBO;
instance_p->max_frame_size = FXMAC_MAX_FRAME_SIZE_JUMBO;
reg_new_netcfg |= FXMAC_NWCFG_JUMBO_MASK;
FXMAC_WRITEREG32(config_p->base_address,
FXMAC_JUMBOMAXLEN_OFFSET, FXMAC_MAX_FRAME_SIZE_JUMBO);
FXMAC_WRITEREG32(config_p->base_address,
FXMAC_TXQSEGALLOC_QLOWER_OFFSET,FXMAC_TXQSEGALLOC_QLOWER_MASK);
if (queue_num == 0)
{
u32 rx_buf_size = 0;
reg = FXMAC_READREG32(config_p->base_address,
FXMAC_DMACR_OFFSET);
reg &= ~FXMAC_DMACR_RXBUF_MASK;
rx_buf_size = ((u32)instance_p->max_frame_size / (u32)FXMAC_RX_BUF_UNIT);
rx_buf_size += (((u32)instance_p->max_frame_size % (u32)FXMAC_RX_BUF_UNIT) != (u32)0) ? 1U : 0U;
reg |= ((rx_buf_size << (u32)(FXMAC_DMACR_RXBUF_SHIFT)) &
(u32)(FXMAC_DMACR_RXBUF_MASK));
FXMAC_WRITEREG32(config_p->base_address,
FXMAC_DMACR_OFFSET, reg);
}
else if (queue_num < instance_p->config.max_queue_num)
{
u32 rx_buf_size = 0;
rx_buf_size = ((u32)instance_p->max_frame_size / (u32)FXMAC_RX_BUF_UNIT);
rx_buf_size += (((u32)instance_p->max_frame_size % (u32)FXMAC_RX_BUF_UNIT) != (u32)0) ? 1U : 0U;
FXMAC_WRITEREG32(config_p->base_address, FXMAC_RXBUFQX_SIZE_OFFSET(queue_num), rx_buf_size & FXMAC_RXBUFQX_SIZE_MASK);
}
}
if (((options & FXMAC_SGMII_ENABLE_OPTION) != 0x00000000U))
{
reg_new_netcfg |= (FXMAC_NWCFG_SGMII_MODE_ENABLE_MASK |
FXMAC_NWCFG_PCSSEL_MASK);
}
if ((options & FXMAC_LOOPBACK_NO_MII_OPTION) != 0x00000000U)
{
reg = FXMAC_READREG32(config_p->base_address, FXMAC_NWCTRL_OFFSET);
reg |= FXMAC_NWCTRL_LOOPBACK_LOCAL_MASK;
FXMAC_WRITEREG32(config_p->base_address, FXMAC_NWCTRL_OFFSET, reg);
}
if ((options & FXMAC_LOOPBACK_USXGMII_OPTION) != 0x00000000U)
{
FXMAC_WRITEREG32(config_p->base_address, FXMAC_TEST_CONTROL_OFFSET, 2);
}
/* Officially change the NET_CONFIG registers if it needs to be
* modified.
*/
if (reg_netcfg != reg_new_netcfg)
{
FXMAC_WRITEREG32(config_p->base_address,
FXMAC_NWCFG_OFFSET, reg_new_netcfg);
}
/* Enable TX checksum offload */
if ((options & FXMAC_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U)
{
reg = FXMAC_READREG32(config_p->base_address,
FXMAC_DMACR_OFFSET);
reg |= FXMAC_DMACR_TCPCKSUM_MASK;
FXMAC_WRITEREG32(config_p->base_address,
FXMAC_DMACR_OFFSET, reg);
}
/* Enable transmitter */
if ((options & FXMAC_TRANSMITTER_ENABLE_OPTION) != 0x00000000U)
{
reg = FXMAC_READREG32(config_p->base_address,
FXMAC_NWCTRL_OFFSET);
reg |= FXMAC_NWCTRL_TXEN_MASK;
FXMAC_WRITEREG32(config_p->base_address,
FXMAC_NWCTRL_OFFSET, reg);
}
/* Enable receiver */
if ((options & FXMAC_RECEIVER_ENABLE_OPTION) != 0x00000000U)
{
reg = FXMAC_READREG32(config_p->base_address,
FXMAC_NWCTRL_OFFSET);
reg |= FXMAC_NWCTRL_RXEN_MASK;
FXMAC_WRITEREG32(config_p->base_address,
FXMAC_NWCTRL_OFFSET, reg);
}
/* The remaining options not handled here are managed elsewhere in the
* driver. No register modifications are needed at this time. Reflecting
* the option in instance_p->options is good enough for now.
*/
/* Set options word to its new value */
instance_p->options |= options;
status = (FError)(FT_SUCCESS);
}
return status;
}
/**
* Clear options for the driver/device
*
* @param instance_p is a pointer to the instance to be worked on.
* @param options are the options to clear. Multiple options can be cleared by
* OR'ing FXMAC_*_options constants together. options not specified
* are not affected.
* @param queue_num is the Buffer Queue Index ,Used for jumbo frames only
* @return
* - FT_SUCCESS if the options were set successfully
* - FXMAC_ERR_MAC_IS_PROCESSING if the device has not yet been stopped
*
* @note
* See fxmac.h for a description of the available options.
*/
FError FXmacClearOptions(FXmac *instance_p, u32 options, u32 queue_num)
{
u32 reg; /* Generic */
u32 reg_net_cfg; /* Reflects original contents of NET_CONFIG */
u32 reg_new_net_cfg; /* Reflects new contents of NET_CONFIG */
FError status;
FXmacConfig *config_p;
FASSERT(instance_p != NULL);
FASSERT(instance_p->is_ready == (u32)FT_COMPONENT_IS_READY);
config_p = &instance_p->config;
/* Be sure device has been stopped */
if (instance_p->is_started == (u32)FT_COMPONENT_IS_STARTED)
{
status = (FError)(FXMAC_ERR_MAC_IS_PROCESSING);
}
else
{
/* Many of these options will change the NET_CONFIG registers.
* To reduce the amount of IO to the device, group these options here
* and change them all at once.
*/
/* Grab current register contents */
reg_net_cfg = FXMAC_READREG32(instance_p->config.base_address,
FXMAC_NWCFG_OFFSET);
reg_new_net_cfg = reg_net_cfg;
/* There is only RX configuration!?
* It is configured in two different length, up to 1536 and 10240 bytes
*/
if ((options & FXMAC_FRAME1536_OPTION) != 0x00000000U)
{
reg_new_net_cfg &= (u32)(~FXMAC_NWCFG_1536RXEN_MASK);
}
/* Turn off VLAN packet only */
if ((options & FXMAC_VLAN_OPTION) != 0x00000000U)
{
reg_new_net_cfg &= (u32)(~FXMAC_NWCFG_NVLANDISC_MASK);
}
/* Turn off FCS stripping on receive packets */
if ((options & FXMAC_FCS_STRIP_OPTION) != 0x00000000U)
{
reg_new_net_cfg &= (u32)(~FXMAC_NWCFG_FCS_REMOVE_MASK);
}
/* Turn off length/type field checking on receive packets */
if ((options & FXMAC_LENTYPE_ERR_OPTION) != 0x00000000U)
{
reg_new_net_cfg &= (u32)(~FXMAC_NWCFG_LENGTH_FIELD_ERROR_FRAME_DISCARD_MASK);
}
/* Turn off flow control */
if ((options & FXMAC_FLOW_CONTROL_OPTION) != 0x00000000U)
{
reg_new_net_cfg &= (u32)(~FXMAC_NWCFG_PAUSE_ENABLE_MASK);
}
/* Turn off promiscuous frame filtering (all frames are received) */
if ((options & FXMAC_PROMISC_OPTION) != 0x00000000U)
{
reg_new_net_cfg &= (u32)(~FXMAC_NWCFG_COPYALLEN_MASK);
}
/* Disallow broadcast address filtering => broadcast reception */
if ((options & FXMAC_BROADCAST_OPTION) != 0x00000000U)
{
reg_new_net_cfg |= FXMAC_NWCFG_BCASTDI_MASK;
}
/* Disallow multicast address filtering */
if ((options & FXMAC_MULTICAST_OPTION) != 0x00000000U)
{
reg_new_net_cfg &= (u32)(~FXMAC_NWCFG_MCASTHASHEN_MASK);
}
/* Disable RX checksum offload */
if ((options & FXMAC_RX_CHKSUM_ENABLE_OPTION) != 0x00000000U)
{
reg_new_net_cfg &= (u32)(~FXMAC_NWCFG_RXCHKSUMEN_MASK);
}
/* Disable jumbo frames */
if (((options & FXMAC_JUMBO_ENABLE_OPTION) != 0x00000000U)) /* 恢复之前buffer 容量 */
{
instance_p->max_mtu_size = FXMAC_MTU;
instance_p->max_frame_size = FXMAC_MAX_FRAME_SIZE;
reg_new_net_cfg &= (u32)(~FXMAC_NWCFG_JUMBO_MASK);
reg = FXMAC_READREG32(instance_p->config.base_address,
FXMAC_DMACR_OFFSET);
reg &= ~FXMAC_DMACR_RXBUF_MASK;
FXMAC_WRITEREG32(config_p->base_address,
FXMAC_TXQSEGALLOC_QLOWER_OFFSET,FXMAC_TXQSEGALLOC_QLOWER_CLEAN_MASK);
if (queue_num == 0)
{
u32 rx_buf_size = 0;
reg = FXMAC_READREG32(instance_p->config.base_address, FXMAC_DMACR_OFFSET);
reg &= ~FXMAC_DMACR_RXBUF_MASK;
rx_buf_size = ((u32)instance_p->max_frame_size / (u32)FXMAC_RX_BUF_UNIT);
rx_buf_size += ((u32)instance_p->max_frame_size % ((u32)FXMAC_RX_BUF_UNIT) != (u32)0) ? 1U : 0U;
reg |= ((rx_buf_size << (u32)(FXMAC_DMACR_RXBUF_SHIFT)) & (u32)(FXMAC_DMACR_RXBUF_MASK));
FXMAC_WRITEREG32(instance_p->config.base_address, FXMAC_DMACR_OFFSET, reg);
}
else if (queue_num < instance_p->config.max_queue_num)
{
u32 rx_buf_size = 0;
rx_buf_size = ((u32)instance_p->max_frame_size / (u32)FXMAC_RX_BUF_UNIT);
rx_buf_size += (((u32)instance_p->max_frame_size % (u32)FXMAC_RX_BUF_UNIT) != (u32)0) ? 1U : 0U;
FXMAC_WRITEREG32(config_p->base_address, FXMAC_RXBUFQX_SIZE_OFFSET(queue_num), rx_buf_size & FXMAC_RXBUFQX_SIZE_MASK);
}
}
if (((options & FXMAC_SGMII_ENABLE_OPTION) != 0x00000000U))
{
reg_new_net_cfg &= (u32)(~(FXMAC_NWCFG_SGMII_MODE_ENABLE_MASK |
FXMAC_NWCFG_PCSSEL_MASK));
}
if ((options & FXMAC_LOOPBACK_NO_MII_OPTION) != 0x00000000U)
{
reg = FXMAC_READREG32(config_p->base_address, FXMAC_NWCTRL_OFFSET);
reg &= (u32)(~FXMAC_NWCTRL_LOOPBACK_LOCAL_MASK);
FXMAC_WRITEREG32(config_p->base_address, FXMAC_NWCTRL_OFFSET, reg);
}
if ((options & FXMAC_LOOPBACK_USXGMII_OPTION) != 0x00000000U)
{
FXMAC_WRITEREG32(config_p->base_address, FXMAC_TEST_CONTROL_OFFSET, (FXMAC_READREG32(config_p->base_address, FXMAC_TEST_CONTROL_OFFSET) & ~2));
}
/* Officially change the NET_CONFIG registers if it needs to be
* modified.
*/
if (reg_net_cfg != reg_new_net_cfg)
{
FXMAC_WRITEREG32(instance_p->config.base_address,
FXMAC_NWCFG_OFFSET, reg_new_net_cfg);
}
/* Disable TX checksum offload */
if ((options & FXMAC_TX_CHKSUM_ENABLE_OPTION) != 0x00000000U)
{
reg = FXMAC_READREG32(instance_p->config.base_address,
FXMAC_DMACR_OFFSET);
reg &= (u32)(~FXMAC_DMACR_TCPCKSUM_MASK);
FXMAC_WRITEREG32(instance_p->config.base_address,
FXMAC_DMACR_OFFSET, reg);
}
/* Disable transmitter */
if ((options & FXMAC_TRANSMITTER_ENABLE_OPTION) != 0x00000000U)
{
reg = FXMAC_READREG32(instance_p->config.base_address,
FXMAC_NWCTRL_OFFSET);
reg &= (u32)(~FXMAC_NWCTRL_TXEN_MASK);
FXMAC_WRITEREG32(instance_p->config.base_address,
FXMAC_NWCTRL_OFFSET, reg);
}
/* Disable receiver */
if ((options & FXMAC_RECEIVER_ENABLE_OPTION) != 0x00000000U)
{
reg = FXMAC_READREG32(instance_p->config.base_address,
FXMAC_NWCTRL_OFFSET);
reg &= (u32)(~FXMAC_NWCTRL_RXEN_MASK);
FXMAC_WRITEREG32(instance_p->config.base_address,
FXMAC_NWCTRL_OFFSET, reg);
}
/* The remaining options not handled here are managed elsewhere in the
* driver. No register modifications are needed at this time. Reflecting
* option in instance_p->options is good enough for now.
*/
/* Set options word to its new value */
instance_p->options &= ~options;
status = (FError)(FT_SUCCESS);
}
return status;
}
/**
* Clear the Hash registers for the mac address pointed by address_ptr.
*
* @param instance_p is a pointer to the instance to be worked on.
*
*/
void FXmacClearHash(FXmac *instance_p)
{
FASSERT(instance_p != NULL);
FASSERT(instance_p->is_ready == (u32)FT_COMPONENT_IS_READY);
FXMAC_WRITEREG32(instance_p->config.base_address,
FXMAC_HASHL_OFFSET, 0x0U);
/* write bits [63:32] in TOP */
FXMAC_WRITEREG32(instance_p->config.base_address,
FXMAC_HASHH_OFFSET, 0x0U);
}
/**
* Write data to the specified PHY register. The Ethernet driver does not
* require the device to be stopped before writing to the PHY. Although it is
* probably a good idea to stop the device, it is the responsibility of the
* application to deem this necessary. The MAC provides the driver with the
* ability to talk to a PHY that adheres to the Media Independent Interface
* (MII) as defined in the IEEE 802.3 standard.
*
* Prior to PHY access with this function, the user should have setup the MDIO
* clock with FXmacSetMdioDivisor().
*
* @param instance_p is a pointer to the FXmac instance to be worked on.
* @param phy_address is the address of the PHY to be written (supports multiple
* PHYs)
* @param register_num is the register number, 0-31, of the specific PHY register
* to write
* @param phy_data is the 16-bit value that will be written to the register
*
* @return
*
* - FT_SUCCESS if the PHY was written to successfully. Since there is no error
* status from the MAC on a write, the user should read the PHY to verify the
* write was successful.
* - FXMAC_ERR_PHY_BUSY if there is another PHY operation in progress
*
* @note
*
* This function is not thread-safe. The user must provide mutually exclusive
* access to this function if there are to be multiple threads that can call it.
*
* There is the possibility that this function will not return if the hardware
* is broken (i.e., it never sets the status bit indicating that the write is
* done). If this is of concern to the user, the user should provide a mechanism
* suitable to their needs for recovery.
*
* For the duration of this function, all host interface reads and writes are
* blocked to the current FXmac instance.
*
******************************************************************************/
FError FXmacPhyWrite(FXmac *instance_p, u32 phy_address,
u32 register_num, u16 phy_data)
{
u32 mgtcr;
volatile u32 ipisr;
u32 ip_write_temp;
FError status;
FASSERT(instance_p != NULL);
/* Make sure no other PHY operation is currently in progress */
if ((!(FXMAC_READREG32(instance_p->config.base_address,
FXMAC_NWSR_OFFSET) &
FXMAC_NWSR_MDIOIDLE_MASK)) == TRUE)
{
status = (FError)(FXMAC_ERR_PHY_BUSY);
}
else
{
/* Construct mgtcr mask for the operation */
mgtcr = FXMAC_PHYMNTNC_OP_MASK | FXMAC_PHYMNTNC_OP_W_MASK |
(phy_address << FXMAC_PHYMNTNC_PHAD_SHFT_MSK) |
(register_num << FXMAC_PHYMNTNC_PREG_SHFT_MSK) | (u32)phy_data;
/* Write mgtcr and wait for completion */
FXMAC_WRITEREG32(instance_p->config.base_address,
FXMAC_PHYMNTNC_OFFSET, mgtcr);
do
{
ipisr = FXMAC_READREG32(instance_p->config.base_address,
FXMAC_NWSR_OFFSET);
ip_write_temp = ipisr;
}
while ((ip_write_temp & FXMAC_NWSR_MDIOIDLE_MASK) == 0x00000000U);
status = (FError)(FT_SUCCESS);
}
return status;
}
/**
* Read the current value of the PHY register indicated by the phy_address and
* the register_num parameters. The MAC provides the driver with the ability to
* talk to a PHY that adheres to the Media Independent Interface (MII) as
* defined in the IEEE 802.3 standard.
*
*
* @param instance_p is a pointer to the FXmac instance to be worked on.
* @param phy_address is the address of the PHY to be read (supports multiple
* PHYs)
* @param register_num is the register number, 0-31, of the specific PHY register
* to read
* @param phydat_aptr is an output parameter, and points to a 16-bit buffer into
* which the current value of the register will be copied.
*
* @return
*
* - FT_SUCCESS if the PHY was read from successfully
* - FXMAC_ERR_PHY_BUSY if there is another PHY operation in progress
*
* @note
*
* This function is not thread-safe. The user must provide mutually exclusive
* access to this function if there are to be multiple threads that can call it.
*
* There is the possibility that this function will not return if the hardware
* is broken (i.e., it never sets the status bit indicating that the read is
* done). If this is of concern to the user, the user should provide a mechanism
* suitable to their needs for recovery.
*
* For the duration of this function, all host interface reads and writes are
* blocked to the current FXmac instance.
*
******************************************************************************/
FError FXmacPhyRead(FXmac *instance_p, u32 phy_address,
u32 register_num, u16 *phydat_aptr)
{
u32 mgtcr;
volatile u32 ipisr;
u32 IpReadTemp;
FError status;
FASSERT(instance_p != NULL);
/* Make sure no other PHY operation is currently in progress */
if ((!(FXMAC_READREG32(instance_p->config.base_address,
FXMAC_NWSR_OFFSET) &
FXMAC_NWSR_MDIOIDLE_MASK)) == TRUE)
{
status = (FError)(FXMAC_ERR_PHY_BUSY);
}
else
{
/* Construct mgtcr mask for the operation */
mgtcr = FXMAC_PHYMNTNC_OP_MASK | FXMAC_PHYMNTNC_OP_R_MASK |
(phy_address << FXMAC_PHYMNTNC_PHAD_SHFT_MSK) |
(register_num << FXMAC_PHYMNTNC_PREG_SHFT_MSK);
/* Write mgtcr and wait for completion */
FXMAC_WRITEREG32(instance_p->config.base_address,
FXMAC_PHYMNTNC_OFFSET, mgtcr);
do
{
ipisr = FXMAC_READREG32(instance_p->config.base_address,
FXMAC_NWSR_OFFSET);
IpReadTemp = ipisr;
}
while ((IpReadTemp & FXMAC_NWSR_MDIOIDLE_MASK) == 0x00000000U);
/* Read data */
*phydat_aptr = (u16)FXMAC_READREG32(instance_p->config.base_address,
FXMAC_PHYMNTNC_OFFSET);
status = (FError)(FT_SUCCESS);
}
return status;
}
boolean FXmacUsxLinkStatus(FXmac *instance_p)
{
u32 reg = 0;
FASSERT(instance_p != NULL);
reg = FXMAC_READREG32(instance_p->config.base_address, FXMAC_GEM_USX_STATUS_OFFSET);
if (reg & FXMAC_GEM_USX_STATUS_BLOCK_LOCK)
{
return TRUE;
}
else
{
return FALSE;
}
}