Add files via upload
This commit is contained in:
parent
a899ec8355
commit
4059938c56
74
Readme.md
74
Readme.md
@ -1,26 +1,94 @@
|
||||
# Toshiba Electronic Devices & Storage Corporation TC956X PCIe Ethernet Host Driver
|
||||
Release Date: 26 Mar 2021
|
||||
Release Date: 05 Jul 2021
|
||||
|
||||
Release Version: V_01-00
|
||||
Release Version: V_01-00-01 : Limited-tested version
|
||||
|
||||
TC956X PCIe EMAC driver is based on "Fedora 30, kernel-5.4.19".
|
||||
|
||||
# Compilation & Run: Need to be root user to execute the following steps.
|
||||
1. Execute following commands:
|
||||
|
||||
#make clean
|
||||
|
||||
#make
|
||||
2. Load phylink module
|
||||
|
||||
#modprobe phylink
|
||||
3. Load the driver
|
||||
|
||||
#insmod tc956x_pcie_eth.ko tc956x_speed=X
|
||||
|
||||
In the module parameter tc956x_speed, X is the desired PCIe Gen speed. X can be 3 or 2 or 1.
|
||||
Passing module parameter (tc956x_speed=X) is optional.
|
||||
If module parameter is not passed, by default Gen3 speed will be selected by the driver.
|
||||
4. Remove the driver
|
||||
|
||||
#rmmod tc956x_pcie_eth
|
||||
|
||||
# Release Versions:
|
||||
|
||||
## TC956X_Host_Driver_20210326_V_01-00:
|
||||
|
||||
1. Initial Version
|
||||
1. Initial Version
|
||||
|
||||
## TC956X_Host_Driver_20210705_V_01-00-01:
|
||||
|
||||
1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
2. XFI interface supported and added module parameters for selection of Port0 and Port1 interface
|
||||
3. kernel_read API replaced with kernel_read_file_from_path API
|
||||
4. sprintf, vsprintf APIs replaced with vcnsprintf or vcnsprintf APIs
|
||||
5. API to print IPA DMA channel statistics supported
|
||||
6. Correction of print statement about selection of C45 PHY for Port0 interface
|
||||
|
||||
# Note:
|
||||
|
||||
1. Use below commands to advertise with Autonegotiation ON for speeds 10Gbps, 5Gbps, 2.5Gbps, 1Gbps, 100Mbps and 10Mbps as ethtool speed command does not support.
|
||||
|
||||
ethtool -s <interface> advertise 0x1000 autoneg on --> changes the advertisement to 10Gbps
|
||||
|
||||
ethtool -s <interface> advertise 0x1000000000000 autoneg on --> changes the advertisement to 5Gbps
|
||||
|
||||
ethtool -s <interface> advertise 0x800000000000 autoneg on --> changes the advertisement to 2.5Gbps
|
||||
|
||||
ethtool -s <interface> advertise 0x020 autoneg on --> changes the advertisement to 1Gbps
|
||||
|
||||
ethtool -s <interface> advertise 0x008 autoneg on --> changes the advertisement to 100Mbps
|
||||
|
||||
ethtool -s <interface> advertise 0x002 autoneg on --> changes the advertisement 10Mbps
|
||||
|
||||
2. Use the below command to insert the kernel module with specific modes for interfaces:
|
||||
|
||||
#insmod tc956x_pcie_eth.ko tc956x_port0_interface=x tc956x_port1_interface=y
|
||||
|
||||
argument info:
|
||||
tc956x_port0_interface: For PORT0 interface mode setting
|
||||
tc956x_port1_interface: For PORT1 interface mode setting
|
||||
x = [0: USXGMII, 1: XFI (default), 2: RGMII (unsupported), 3: SGMII]
|
||||
y = [0: USXGMII (unsupported), 1: XFI (unsupported), 2: RGMII, 3: SGMII(default)]
|
||||
|
||||
If invalid and unsupported modes are passed as kernel module parameter, the default interface mode will be selected.
|
||||
|
||||
3. Regarding the performance, use the below command to increase the dynamic byte queue limit
|
||||
|
||||
$echo "900000" > /sys/devices/pci0000\:00/0000\:00\:01.0/0000\:01\:00.0/0000\:02\:03.0/0000\:05\:00.0/net/enp5s0f0/queues/tx-0/byte_queue_limits/limit_min
|
||||
900000 is the random value chosen. It needs to adjust this value on their system and check
|
||||
"0000\:00/0000\:00\:01.0/0000\:01\:00.0/0000\:02\:03.0/0000\:05\:00.0/" value can be obtained from the "lspci -t" command
|
||||
|
||||
4. The debug counters to check the interrupt count is available.
|
||||
|
||||
"#ethtool -S <interface>" needs to be executed and sample output is as below
|
||||
|
||||
total_interrupts: 120109
|
||||
lpi_intr_n: 0
|
||||
pmt_intr_n: 0
|
||||
event_intr_n: 0
|
||||
tx_intr_n: 120000
|
||||
rx_intr_n: 51
|
||||
xpcs_intr_n: 0
|
||||
phy_intr_n: 46
|
||||
sw_msi_n: 12
|
||||
|
||||
tx_intr_n = No of. Tx interrupts originating from eMAC
|
||||
sw_msi_n = No. of SW MSIs triggered by Systick Handler as part of optimized Tx Timer based on Systick approach.
|
||||
So total number of interrupts for Tx = tx_intr_n + sw_msi_n
|
||||
Please note that whenever Rx interruts are generated, the Host ISR will process the Tx completed descriptors too.
|
||||
|
30
common.h
30
common.h
@ -30,6 +30,10 @@
|
||||
*
|
||||
* 15 Mar 2021 : Base lined
|
||||
* VERSION : 01-00
|
||||
*
|
||||
* 05 Jul 2021 : 1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
* 2. XFI interface support and module parameters for selection of Port0 and Port1 interface
|
||||
* VERSION : 01-00-01
|
||||
*/
|
||||
|
||||
#ifndef __COMMON_H__
|
||||
@ -64,7 +68,7 @@
|
||||
#define DWXGMAC_CORE_3_01 0x30
|
||||
|
||||
//#define DISABLE_EMAC_PORT1
|
||||
|
||||
//#define DUMP_REGISTER
|
||||
/* Note: Multiple macro definitions for TC956X_PCIE_LOGSTAT.
|
||||
* Please also define/undefine same macro in tc956xmac_ioctl.h, if changing in this file
|
||||
*/
|
||||
@ -747,6 +751,11 @@ enum packets_types {
|
||||
|
||||
#ifdef TC956X
|
||||
#define TC956X_EXT_PHY_ETH_INT BIT(20)
|
||||
|
||||
#ifdef TC956X_SW_MSI
|
||||
#define TC956X_SW_MSI_INT BIT(24)
|
||||
#endif
|
||||
|
||||
#define TC956X_SSREG_BRREG_REG_BASE (0x00024000U)
|
||||
|
||||
#define TC956X_GLUE_LOGIC_BASE_OFST (0x0002C000U)
|
||||
@ -901,6 +910,10 @@ enum packets_types {
|
||||
|
||||
#define MSI_INT_TX_CH0 3
|
||||
#define MSI_INT_RX_CH0 11
|
||||
#define MSI_INT_EXT_PHY 20
|
||||
#ifdef TC956X_SW_MSI
|
||||
#define MSI_INT_SW_MSI 24
|
||||
#endif
|
||||
|
||||
#define TC956X_MSI_BASE (0xF000)
|
||||
#define TC956X_MSI_PF0 (0x000)
|
||||
@ -936,6 +949,10 @@ enum packets_types {
|
||||
(pf_id * TC956X_MSI_PF1) + (0x0038))
|
||||
#define TC956X_MSI_VECT_SET7_OFFSET(pf_id) (TC956X_MSI_BASE +\
|
||||
(pf_id * TC956X_MSI_PF1) + (0x003C))
|
||||
#define TC956X_MSI_SW_MSI_SET(pf_id) (TC956X_MSI_BASE +\
|
||||
(pf_id * TC956X_MSI_PF1) + (0x0050))
|
||||
#define TC956X_MSI_SW_MSI_CLR(pf_id) (TC956X_MSI_BASE +\
|
||||
(pf_id * TC956X_MSI_PF1) + (0x0054))
|
||||
#define TC956X_MSI_EVENT_OFFSET(pf_id) (TC956X_MSI_BASE +\
|
||||
(pf_id * TC956X_MSI_PF1) + (0x0068))
|
||||
|
||||
@ -1126,6 +1143,17 @@ struct tc956xmac_extra_stats {
|
||||
u64 rxch_sw_cur_rx[TC956XMAC_CH_MAX];
|
||||
u64 rxch_sw_dirty_rx[TC956XMAC_CH_MAX];
|
||||
|
||||
/*debug interrupt counters */
|
||||
u64 total_interrupts;
|
||||
u64 lpi_intr_n;
|
||||
u64 pmt_intr_n;
|
||||
u64 event_intr_n;
|
||||
u64 tx_intr_n;
|
||||
u64 rx_intr_n;
|
||||
u64 xpcs_intr_n;
|
||||
u64 phy_intr_n;
|
||||
u64 sw_msi_n;
|
||||
|
||||
};
|
||||
|
||||
/* Safety Feature statistics exposed by ethtool */
|
||||
|
@ -30,7 +30,11 @@
|
||||
*
|
||||
* 15 Mar 2021 : Base lined
|
||||
* VERSION : 01-00
|
||||
*/
|
||||
*
|
||||
* 05 Jul 2021 : 1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
* 2. XFI interface support and module parameters for selection of Port0 and Port1 interface
|
||||
* VERSION : 01-00-01
|
||||
*/
|
||||
|
||||
#include <linux/bitrev.h>
|
||||
#include <linux/crc32.h>
|
||||
@ -64,7 +68,8 @@ static void dwxgmac2_core_init(struct tc956xmac_priv *priv,
|
||||
tx |= hw->link.xgmii.speed10000;
|
||||
break;
|
||||
case SPEED_2500:
|
||||
tx |= hw->link.speed2500;
|
||||
if (priv->plat->interface == PHY_INTERFACE_MODE_SGMII)
|
||||
tx |= hw->link.speed2500;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
default:
|
||||
@ -77,7 +82,8 @@ static void dwxgmac2_core_init(struct tc956xmac_priv *priv,
|
||||
tx |= hw->link.speed1000;
|
||||
else if (priv->plat->interface == PHY_INTERFACE_MODE_SGMII)
|
||||
tx |= hw->link.speed2500;
|
||||
else if (priv->plat->interface == PHY_INTERFACE_MODE_USXGMII)
|
||||
else if ((priv->plat->interface == PHY_INTERFACE_MODE_USXGMII) ||
|
||||
(priv->plat->interface == PHY_INTERFACE_MODE_10GKR))
|
||||
tx |= hw->link.xgmii.speed10000;
|
||||
#endif
|
||||
writel(tx, ioaddr + XGMAC_TX_CONFIG);
|
||||
@ -2394,6 +2400,7 @@ static int dwxgmac3_est_configure(struct tc956xmac_priv *priv,
|
||||
u64 read_btr = 0, read_ctr = 0;
|
||||
static u32 switch_cnt = 0;
|
||||
char *qptr = NULL, *pptr = NULL;
|
||||
int char_buff_size = 100*100;
|
||||
|
||||
pptr = (char *)kzalloc(100*100, GFP_KERNEL);
|
||||
if (!pptr) {
|
||||
@ -2442,9 +2449,9 @@ static int dwxgmac3_est_configure(struct tc956xmac_priv *priv,
|
||||
switch_cnt, read_btr, read_ctr,
|
||||
PACKET_IPG, PACKET_CDT_IPG);
|
||||
for (i = 0; i < cfg->gcl_size; i++) {
|
||||
sprintf((pptr+(i*11)), ", %010d", (cfg->gcl[i]&0xffffff));
|
||||
scnprintf((pptr+(i*11)), char_buff_size - (i*11), ",%010d", (cfg->gcl[i]&0xffffff));
|
||||
for (j = 0; j < 6; j++) {
|
||||
sprintf((qptr+(i*6*2)+(j*2)), ",%d",
|
||||
scnprintf((qptr+(i*6*2)+(j*2)), char_buff_size - (i*6*2) + (j*2), ",%d",
|
||||
((cfg->gcl[i]>>(24+j))&0x1));
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,10 @@
|
||||
*
|
||||
* 15 Mar 2021 : Base lined
|
||||
* VERSION : 01-00
|
||||
*
|
||||
* 05 Jul 2021 : 1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
* 2. XFI interface support and module parameters for selection of Port0 and Port1 interface
|
||||
* VERSION : 01-00-01
|
||||
*/
|
||||
|
||||
#include <linux/dma-mapping.h>
|
||||
@ -1446,5 +1450,71 @@ int stop_channel(struct net_device *ndev, struct channel_info *channel)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(stop_channel);
|
||||
|
||||
/*!
|
||||
* \brief This API will print EMAC-IPA offload DMA channel stats
|
||||
*
|
||||
* \details This function will read and prints DMA Descriptor stats
|
||||
* used by IPA.
|
||||
*
|
||||
* \param[in] ndev : TC956x netdev data structure.
|
||||
*
|
||||
* \return : Return 0 on success, -ve value on error
|
||||
* -ENODEV if ndev is NULL, tc956xmac_priv extracted from ndev is NULL
|
||||
*/
|
||||
int read_ipa_desc_stats(struct net_device *ndev)
|
||||
{
|
||||
int chno = 0;
|
||||
struct tc956xmac_priv *priv;
|
||||
|
||||
if (!ndev) {
|
||||
pr_err("%s: ERROR: Invalid netdevice pointer\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
priv = netdev_priv(ndev);
|
||||
if (!priv) {
|
||||
pr_err("%s: ERROR: Invalid private data pointer\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* TX DMA Descriptors Status for all channels */
|
||||
for (chno = 0; chno < priv->plat->tx_queues_to_use; chno++) {
|
||||
|
||||
if (priv->plat->tx_dma_ch_owner[chno] != USE_IN_OFFLOADER)
|
||||
continue;
|
||||
|
||||
netdev_info(priv->dev, "%s : txch_status[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_STATUS(chno)));
|
||||
netdev_info(priv->dev, "%s : txch_control[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_TX_CONTROL(chno)));
|
||||
netdev_info(priv->dev, "%s : txch_desc_list_haddr[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_TxDESC_HADDR(chno)));
|
||||
netdev_info(priv->dev, "%s : txch_desc_list_laddr[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_TxDESC_LADDR(chno)));
|
||||
netdev_info(priv->dev, "%s : txch_desc_ring_len[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_TX_CONTROL2(chno)));
|
||||
netdev_info(priv->dev, "%s : txch_desc_curr_haddr[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_Cur_TxDESC_HADDR(chno)));
|
||||
netdev_info(priv->dev, "%s : txch_desc_curr_laddr[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_Cur_TxDESC_LADDR(chno)));
|
||||
netdev_info(priv->dev, "%s : txch_desc_tail[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_TxDESC_TAIL_LPTR(chno)));
|
||||
netdev_info(priv->dev, "%s : txch_desc_buf_haddr[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_Cur_TxBuff_HADDR(chno)));
|
||||
netdev_info(priv->dev, "%s : txch_desc_buf_laddr[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_Cur_TxBuff_LADDR(chno)));
|
||||
netdev_info(priv->dev, "%s : txch_dma_interrupt_en[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_INT_EN(chno)));
|
||||
}
|
||||
|
||||
/* RX DMA Descriptors Status for all channels */
|
||||
for (chno = 0; chno < TC956XMAC_CH_MAX; chno++) {
|
||||
|
||||
if (priv->plat->rx_dma_ch_owner[chno] != USE_IN_OFFLOADER)
|
||||
continue;
|
||||
|
||||
netdev_info(priv->dev, "%s : rxch_status[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_STATUS(chno)));
|
||||
netdev_info(priv->dev, "%s : rxch_control[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_RX_CONTROL(chno)));
|
||||
netdev_info(priv->dev, "%s : rxch_desc_list_haddr[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_RxDESC_HADDR(chno)));
|
||||
netdev_info(priv->dev, "%s : rxch_desc_list_laddr[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_RxDESC_LADDR(chno)));
|
||||
netdev_info(priv->dev, "%s : rxch_desc_ring_len[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_RX_CONTROL2(chno)));
|
||||
netdev_info(priv->dev, "%s : rxch_desc_curr_haddr[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_Cur_RxDESC_HADDR(chno)));
|
||||
netdev_info(priv->dev, "%s : rxch_desc_curr_laddr[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_Cur_RxDESC_LADDR(chno)));
|
||||
netdev_info(priv->dev, "%s : rxch_desc_tail[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_RxDESC_TAIL_LPTR(chno)));
|
||||
netdev_info(priv->dev, "%s : rxch_desc_buf_haddr[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_Cur_RxBuff_HADDR(chno)));
|
||||
netdev_info(priv->dev, "%s : rxch_desc_buf_laddr[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_Cur_RxBuff_LADDR(chno)));
|
||||
netdev_info(priv->dev, "%s : rxch_dma_interrupt_en[%d] : 0x%08x", __func__, chno, readl(priv->ioaddr + XGMAC_DMA_CH_INT_EN(chno)));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(read_ipa_desc_stats);
|
||||
|
@ -29,6 +29,10 @@
|
||||
*
|
||||
* 15 Mar 2021 : Base lined
|
||||
* VERSION : 01-00
|
||||
*
|
||||
* 05 Jul 2021 : 1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
* 2. XFI interface support and module parameters for selection of Port0 and Port1 interface
|
||||
* VERSION : 01-00-01
|
||||
*/
|
||||
|
||||
#ifndef __TC956x_IPA_INTF_H
|
||||
@ -363,6 +367,19 @@ int start_channel(struct net_device *ndev, struct channel_info *channel);
|
||||
*/
|
||||
int stop_channel(struct net_device *ndev, struct channel_info *channel);
|
||||
|
||||
/*!
|
||||
* \brief This API will print EMAC-IPA offload DMA channel stats
|
||||
*
|
||||
* \details This function will read and prints DMA Descriptor stats
|
||||
* used by IPA.
|
||||
*
|
||||
* \param[i] ndev : TC956x netdev data structure.
|
||||
*
|
||||
* \return : Return 0 on success, -ve value on error
|
||||
* -ENODEV if ndev is NULL, tc956xmac_priv extracted from ndev is NULL
|
||||
*
|
||||
*/
|
||||
int read_ipa_desc_stats(struct net_device *ndev);
|
||||
|
||||
#endif /* __TC956x_IPA_INTF_H */
|
||||
|
||||
|
147
tc956x_pci.c
147
tc956x_pci.c
@ -30,6 +30,10 @@
|
||||
*
|
||||
* 15 Mar 2021 : Base lined
|
||||
* VERSION : 01-00
|
||||
*
|
||||
* 05 Jul 2021 : 1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
* 2. XFI interface support and module parameters for selection of Port0 and Port1 interface
|
||||
* VERSION : 01-00-01
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
@ -56,9 +60,10 @@
|
||||
#ifdef TC956X_PCIE_GEN3_SETTING
|
||||
static unsigned int tc956x_speed = 3;
|
||||
#endif
|
||||
static unsigned int tc956x_port0_interface = ENABLE_XFI_INTERFACE;
|
||||
static unsigned int tc956x_port1_interface = ENABLE_SGMII_INTERFACE;
|
||||
|
||||
|
||||
static const struct tc956x_version tc956x_drv_version = {0, 1, 0, 0};
|
||||
static const struct tc956x_version tc956x_drv_version = {0, 1, 0, 0, 0, 1};
|
||||
|
||||
/*
|
||||
* This struct is used to associate PCI Function of MAC controller on a board,
|
||||
@ -674,21 +679,15 @@ static void xgmac_default_data(struct plat_tc956xmacenet_data *plat)
|
||||
plat->has_gmac4 = 0;
|
||||
plat->force_thresh_dma_mode = 0;
|
||||
plat->mdio_bus_data->needs_reset = false;
|
||||
if (INTERFACE_SELECTED(plat->port_num) == ENABLE_USXGMII_INTERFACE)
|
||||
if ((plat->port_interface == ENABLE_USXGMII_INTERFACE) ||
|
||||
(plat->port_interface == ENABLE_XFI_INTERFACE))
|
||||
plat->mac_port_sel_speed = 10000;
|
||||
|
||||
|
||||
if (INTERFACE_SELECTED(plat->port_num) == ENABLE_RGMII_INTERFACE)
|
||||
if (plat->port_interface == ENABLE_RGMII_INTERFACE)
|
||||
plat->mac_port_sel_speed = 1000;
|
||||
|
||||
|
||||
if (INTERFACE_SELECTED(plat->port_num) == ENABLE_SGMII_INTERFACE) {
|
||||
#ifndef TC956X_SGMII_2P5_GBPS_TEST
|
||||
plat->mac_port_sel_speed = 1000;
|
||||
#else
|
||||
if (plat->port_interface == ENABLE_SGMII_INTERFACE)
|
||||
plat->mac_port_sel_speed = 2500;
|
||||
#endif
|
||||
}
|
||||
|
||||
plat->riwt_off = 0;
|
||||
plat->rss_en = 0;
|
||||
@ -724,23 +723,21 @@ static int tc956xmac_xgmac3_default_data(struct pci_dev *pdev,
|
||||
plat->pdev = pdev;
|
||||
|
||||
#ifdef TC956X
|
||||
if (INTERFACE_SELECTED(plat->port_num) == ENABLE_USXGMII_INTERFACE) {
|
||||
if (plat->port_interface == ENABLE_USXGMII_INTERFACE) {
|
||||
plat->interface = PHY_INTERFACE_MODE_USXGMII;
|
||||
plat->max_speed = 10000;
|
||||
}
|
||||
|
||||
if (INTERFACE_SELECTED(plat->port_num) == ENABLE_RGMII_INTERFACE) {
|
||||
if (plat->port_interface == ENABLE_XFI_INTERFACE) {
|
||||
plat->interface = PHY_INTERFACE_MODE_10GKR;
|
||||
plat->max_speed = 10000;
|
||||
}
|
||||
if (plat->port_interface == ENABLE_RGMII_INTERFACE) {
|
||||
plat->interface = PHY_INTERFACE_MODE_RGMII;
|
||||
plat->max_speed = 1000;
|
||||
}
|
||||
|
||||
if (INTERFACE_SELECTED(plat->port_num) == ENABLE_SGMII_INTERFACE) {
|
||||
if (plat->port_interface == ENABLE_SGMII_INTERFACE) {
|
||||
plat->interface = PHY_INTERFACE_MODE_SGMII;
|
||||
#ifndef TC956X_SGMII_2P5_GBPS_TEST
|
||||
plat->max_speed = 1000;
|
||||
#else
|
||||
plat->max_speed = 2500;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
plat->interface = PHY_INTERFACE_MODE_USXGMII;
|
||||
@ -1729,10 +1726,11 @@ static int tc956xmac_pci_probe(struct pci_dev *pdev,
|
||||
struct tc956x_ltssm_log ltssm_data;
|
||||
#endif/*TC956X_PCIE_LOGSTAT*/
|
||||
KPRINT_INFO("%s >", __func__);
|
||||
sprintf(version_str, "Host Driver Version %d%d-%d%d",
|
||||
scnprintf(version_str, sizeof(version_str), "Host Driver Version %d%d-%d%d-%d%d",
|
||||
tc956x_drv_version.rel_dbg,
|
||||
tc956x_drv_version.major, tc956x_drv_version.minor,
|
||||
tc956x_drv_version.sub_minor);
|
||||
tc956x_drv_version.sub_minor,
|
||||
tc956x_drv_version.patch_rel_major, tc956x_drv_version.patch_rel_minor);
|
||||
NMSGPR_INFO(&pdev->dev, "%s\n", version_str);
|
||||
|
||||
plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
|
||||
@ -1896,6 +1894,26 @@ static int tc956xmac_pci_probe(struct pci_dev *pdev,
|
||||
plat->c45_needed = PORT1_C45_STATE;
|
||||
}
|
||||
|
||||
if (res.port_num == RM_PF0_ID) {
|
||||
/* Set the PORT0 interface mode to default, in case of invalid input */
|
||||
if ((tc956x_port0_interface == ENABLE_RGMII_INTERFACE) ||
|
||||
(tc956x_port0_interface > ENABLE_SGMII_INTERFACE))
|
||||
tc956x_port0_interface = ENABLE_XFI_INTERFACE;
|
||||
|
||||
res.port_interface = tc956x_port0_interface;
|
||||
}
|
||||
|
||||
if (res.port_num == RM_PF1_ID) {
|
||||
/* Set the PORT1 interface mode to default, in case of invalid input */
|
||||
if ((tc956x_port1_interface < ENABLE_RGMII_INTERFACE) ||
|
||||
(tc956x_port1_interface > ENABLE_SGMII_INTERFACE))
|
||||
tc956x_port1_interface = ENABLE_SGMII_INTERFACE;
|
||||
|
||||
res.port_interface = tc956x_port1_interface;
|
||||
}
|
||||
|
||||
plat->port_interface = res.port_interface;
|
||||
|
||||
ret = info->setup(pdev, plat);
|
||||
|
||||
if (ret)
|
||||
@ -1974,25 +1992,23 @@ static int tc956xmac_pci_probe(struct pci_dev *pdev,
|
||||
ret = readl(res.addr + NCLKCTRL0_OFFSET);
|
||||
|
||||
ret |= ((NCLKCTRL0_MAC0TXCEN | NCLKCTRL0_MAC0ALLCLKEN | NCLKCTRL0_MAC0RXCEN));
|
||||
#ifdef TC956X_SGMII_2P5_GBPS_TEST
|
||||
ret &= ~NCLKCTRL0_POEPLLCEN;
|
||||
ret &= ~NCLKCTRL0_SGMPCIEN;
|
||||
ret &= ~NCLKCTRL0_REFCLKOCEN;
|
||||
ret &= ~NCLKCTRL0_MAC0125CLKEN;
|
||||
ret &= ~NCLKCTRL0_MAC0312CLKEN;
|
||||
#endif
|
||||
/* Only if "current" port is SGMII 2.5G, configure below clocks. */
|
||||
if (res.port_interface == ENABLE_SGMII_INTERFACE) {
|
||||
ret &= ~NCLKCTRL0_POEPLLCEN;
|
||||
ret &= ~NCLKCTRL0_SGMPCIEN;
|
||||
ret &= ~NCLKCTRL0_REFCLKOCEN;
|
||||
ret &= ~NCLKCTRL0_MAC0125CLKEN;
|
||||
ret &= ~NCLKCTRL0_MAC0312CLKEN;
|
||||
}
|
||||
writel(ret, res.addr + NCLKCTRL0_OFFSET);
|
||||
|
||||
/* Interface configuration for port0*/
|
||||
ret = readl(res.addr + NEMAC0CTL_OFFSET);
|
||||
ret &= ~(NEMACCTL_SP_SEL_MASK | NEMACCTL_PHY_INF_SEL_MASK);
|
||||
if (PORT0_INTERFACE == ENABLE_SGMII_INTERFACE)
|
||||
#ifndef TC956X_SGMII_2P5_GBPS_TEST
|
||||
ret |= NEMACCTL_SP_SEL_SGMII_1000M;
|
||||
#else
|
||||
if (res.port_interface == ENABLE_SGMII_INTERFACE)
|
||||
ret |= NEMACCTL_SP_SEL_SGMII_2500M;
|
||||
#endif
|
||||
else if (PORT0_INTERFACE == ENABLE_USXGMII_INTERFACE)
|
||||
else if ((res.port_interface == ENABLE_USXGMII_INTERFACE) ||
|
||||
(res.port_interface == ENABLE_XFI_INTERFACE))
|
||||
ret |= NEMACCTL_SP_SEL_USXGMII_10G_10G;
|
||||
|
||||
ret &= ~(0x00000040); /* Mask Polarity */
|
||||
@ -2021,16 +2037,21 @@ static int tc956xmac_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
ret |= ((NCLKCTRL1_MAC1TXCEN | NCLKCTRL1_MAC1RXCEN |
|
||||
NCLKCTRL1_MAC1ALLCLKEN1 | 1 << 15));
|
||||
if (res.port_interface == ENABLE_SGMII_INTERFACE) {
|
||||
ret &= ~NCLKCTRL1_MAC1125CLKEN1;
|
||||
ret &= ~NCLKCTRL1_MAC1312CLKEN1;
|
||||
}
|
||||
writel(ret, res.addr + NCLKCTRL1_OFFSET);
|
||||
|
||||
/* Interface configuration for port1*/
|
||||
ret = readl(res.addr + NEMAC1CTL_OFFSET);
|
||||
ret &= ~(NEMACCTL_SP_SEL_MASK | NEMACCTL_PHY_INF_SEL_MASK);
|
||||
if (PORT1_INTERFACE == ENABLE_RGMII_INTERFACE)
|
||||
if (res.port_interface == ENABLE_RGMII_INTERFACE)
|
||||
ret |= NEMACCTL_SP_SEL_RGMII_1000M;
|
||||
else if (PORT1_INTERFACE == ENABLE_SGMII_INTERFACE)
|
||||
else if (res.port_interface == ENABLE_SGMII_INTERFACE)
|
||||
ret |= NEMACCTL_SP_SEL_SGMII_2500M;
|
||||
else if (PORT1_INTERFACE == ENABLE_USXGMII_INTERFACE)
|
||||
else if ((res.port_interface == ENABLE_USXGMII_INTERFACE) ||
|
||||
(res.port_interface == ENABLE_XFI_INTERFACE))
|
||||
ret |= NEMACCTL_SP_SEL_USXGMII_10G_10G;
|
||||
|
||||
ret &= ~(0x00000040); /* Mask Polarity */
|
||||
@ -2059,8 +2080,10 @@ static int tc956xmac_pci_probe(struct pci_dev *pdev,
|
||||
goto err_dvr_probe;
|
||||
}
|
||||
#ifdef TC956X
|
||||
writel(0x00000000, res.addr + 0x1050);
|
||||
writel(0xF300F300, res.addr + 0x107C);
|
||||
if ((res.port_num == RM_PF1_ID) && (res.port_interface == ENABLE_RGMII_INTERFACE)) {
|
||||
writel(0x00000000, res.addr + 0x1050);
|
||||
writel(0xF300F300, res.addr + 0x107C);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TC956X_PCIE_LOGSTAT
|
||||
@ -2240,14 +2263,23 @@ static int tc956x_pcie_resume_config(struct pci_dev *pdev)
|
||||
ret = readl(priv->tc956x_SFR_pci_base_addr + NCLKCTRL0_OFFSET);
|
||||
|
||||
ret |= ((NCLKCTRL0_MAC0TXCEN | NCLKCTRL0_MAC0ALLCLKEN | NCLKCTRL0_MAC0RXCEN));
|
||||
if (priv->port_interface == ENABLE_SGMII_INTERFACE) {
|
||||
/* Disable Clocks for 2.5Gbps SGMII */
|
||||
ret &= ~NCLKCTRL0_POEPLLCEN;
|
||||
ret &= ~NCLKCTRL0_SGMPCIEN;
|
||||
ret &= ~NCLKCTRL0_REFCLKOCEN;
|
||||
ret &= ~NCLKCTRL0_MAC0125CLKEN;
|
||||
ret &= ~NCLKCTRL0_MAC0312CLKEN;
|
||||
}
|
||||
writel(ret, priv->tc956x_SFR_pci_base_addr + NCLKCTRL0_OFFSET);
|
||||
|
||||
/* Interface configuration for port0*/
|
||||
ret = readl(priv->tc956x_SFR_pci_base_addr + NEMAC0CTL_OFFSET);
|
||||
ret &= ~(NEMACCTL_SP_SEL_MASK | NEMACCTL_PHY_INF_SEL_MASK);
|
||||
if (PORT0_INTERFACE == ENABLE_SGMII_INTERFACE)
|
||||
ret |= NEMACCTL_SP_SEL_SGMII_1000M; //ret |= NEMACCTL_SP_SEL_SGMII_2500M;
|
||||
else if (PORT0_INTERFACE == ENABLE_USXGMII_INTERFACE)
|
||||
if (priv->port_interface == ENABLE_SGMII_INTERFACE)
|
||||
ret |= NEMACCTL_SP_SEL_SGMII_2500M;
|
||||
else if ((priv->port_interface == ENABLE_USXGMII_INTERFACE) ||
|
||||
(priv->port_interface == ENABLE_XFI_INTERFACE))
|
||||
ret |= NEMACCTL_SP_SEL_USXGMII_10G_10G;
|
||||
|
||||
ret &= ~(0x00000040); /* Mask Polarity */
|
||||
@ -2276,16 +2308,21 @@ static int tc956x_pcie_resume_config(struct pci_dev *pdev)
|
||||
|
||||
ret |= ((NCLKCTRL1_MAC1TXCEN | NCLKCTRL1_MAC1RXCEN |
|
||||
NCLKCTRL1_MAC1ALLCLKEN1 | 1 << 15));
|
||||
if (priv->port_interface == ENABLE_SGMII_INTERFACE) {
|
||||
ret &= ~NCLKCTRL1_MAC1125CLKEN1;
|
||||
ret &= ~NCLKCTRL1_MAC1312CLKEN1;
|
||||
}
|
||||
writel(ret, priv->tc956x_SFR_pci_base_addr + NCLKCTRL1_OFFSET);
|
||||
|
||||
/* Interface configuration for port1*/
|
||||
ret = readl(priv->tc956x_SFR_pci_base_addr + NEMAC1CTL_OFFSET);
|
||||
ret &= ~(NEMACCTL_SP_SEL_MASK | NEMACCTL_PHY_INF_SEL_MASK);
|
||||
if (PORT1_INTERFACE == ENABLE_RGMII_INTERFACE)
|
||||
if (priv->port_interface == ENABLE_RGMII_INTERFACE)
|
||||
ret |= NEMACCTL_SP_SEL_RGMII_1000M;
|
||||
else if (PORT1_INTERFACE == ENABLE_SGMII_INTERFACE)
|
||||
else if (priv->port_interface == ENABLE_SGMII_INTERFACE)
|
||||
ret |= NEMACCTL_SP_SEL_SGMII_2500M;
|
||||
else if (PORT1_INTERFACE == ENABLE_USXGMII_INTERFACE)
|
||||
else if ((priv->port_interface == ENABLE_USXGMII_INTERFACE) ||
|
||||
(priv->port_interface == ENABLE_XFI_INTERFACE))
|
||||
ret |= NEMACCTL_SP_SEL_USXGMII_10G_10G;
|
||||
|
||||
ret &= ~(0x00000040); /* Mask Polarity */
|
||||
@ -2410,8 +2447,10 @@ static s32 tc956x_pcie_resume(struct pci_dev *pdev)
|
||||
/* Call tc956xmac_resume() */
|
||||
tc956xmac_resume(&pdev->dev);
|
||||
#ifdef TC956X
|
||||
writel(NEMACTXCDLY_DEFAULT, priv->ioaddr + TC9563_CFG_NEMACTXCDLY);
|
||||
writel(NEMACIOCTL_DEFAULT, priv->ioaddr + TC9563_CFG_NEMACIOCTL);
|
||||
if ((priv->port_num == RM_PF1_ID) && (priv->port_interface == ENABLE_RGMII_INTERFACE)) {
|
||||
writel(NEMACTXCDLY_DEFAULT, priv->ioaddr + TC9563_CFG_NEMACTXCDLY);
|
||||
writel(NEMACIOCTL_DEFAULT, priv->ioaddr + TC9563_CFG_NEMACIOCTL);
|
||||
}
|
||||
#endif
|
||||
DBGPR_FUNC(&(pdev->dev), "<--%s\n", __func__);
|
||||
|
||||
@ -2638,6 +2677,16 @@ MODULE_PARM_DESC(tc956x_speed,
|
||||
"PCIe speed Gen TC9563_64 - default is 3, [1..3]");
|
||||
#endif
|
||||
|
||||
module_param(tc956x_port0_interface, uint, 0444);
|
||||
MODULE_PARM_DESC(tc956x_port0_interface,
|
||||
"PORT0 interface mode TC9563_64 - default is 1,\
|
||||
[0: USXGMII, 1: XFI, 2: RGMII(not supported), 3: SGMII]");
|
||||
|
||||
module_param(tc956x_port1_interface, uint, 0444);
|
||||
MODULE_PARM_DESC(tc956x_port1_interface,
|
||||
"PORT1 interface mode TC9563_64 - default is 3,\
|
||||
[0: USXGMII(not supported), 1: XFI(not supported), 2: RGMII, 3: SGMII]");
|
||||
|
||||
MODULE_DESCRIPTION("TC956X PCI Express Ethernet Network Driver");
|
||||
MODULE_AUTHOR("Toshiba Electronic Devices & Storage Corporation");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -27,6 +27,10 @@
|
||||
*
|
||||
* 15 Mar 2021 : Base lined
|
||||
* VERSION : 01-00
|
||||
*
|
||||
* 05 Jul 2021 : 1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
* 2. XFI interface support and module parameters for selection of Port0 and Port1 interface
|
||||
* VERSION : 01-00-01
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
@ -93,21 +97,26 @@ int tc956x_xpcs_init(struct tc956xmac_priv *priv, void __iomem *xpcsaddr)
|
||||
reg_value |= XGMAC_SGMII_MODE;/*SGMII PCS MODE*/
|
||||
tc956x_xpcs_write(xpcsaddr, XGMAC_VR_MII_AN_CTRL, reg_value);
|
||||
|
||||
#ifdef TC956X_SGMII_2P5_GBPS_TEST
|
||||
reg_value = tc956x_xpcs_read(xpcsaddr, XGMAC_VR_XS_PCS_DIG_CTRL1);
|
||||
reg_value &= ~(0x4);
|
||||
reg_value |= 0x4; /*EN_2_5G_MODE*/
|
||||
tc956x_xpcs_write(xpcsaddr, XGMAC_VR_XS_PCS_DIG_CTRL1, reg_value);
|
||||
#endif
|
||||
if (priv->is_sgmii_2p5g == true) {
|
||||
reg_value = tc956x_xpcs_read(xpcsaddr, XGMAC_VR_XS_PCS_DIG_CTRL1);
|
||||
reg_value &= ~(0x4);
|
||||
/* Enable only if SGMII 2.5G is enabled */
|
||||
reg_value |= 0x4; /*EN_2_5G_MODE*/
|
||||
tc956x_xpcs_write(xpcsaddr, XGMAC_VR_XS_PCS_DIG_CTRL1, reg_value);
|
||||
}
|
||||
}
|
||||
|
||||
if (priv->plat->interface == PHY_INTERFACE_MODE_USXGMII) {
|
||||
if ((priv->plat->interface == PHY_INTERFACE_MODE_USXGMII) ||
|
||||
(priv->plat->interface == PHY_INTERFACE_MODE_10GKR)) {
|
||||
reg_value = tc956x_xpcs_read(xpcsaddr, XGMAC_SR_XS_PCS_CTRL2);
|
||||
reg_value &= XGMAC_PCS_TYPE_SEL;/*PCS_TYPE_SEL as 10GBASE-R PCS */
|
||||
tc956x_xpcs_write(xpcsaddr, XGMAC_SR_XS_PCS_CTRL2, reg_value);
|
||||
|
||||
reg_value = tc956x_xpcs_read(xpcsaddr, XGMAC_VR_XS_PCS_DIG_CTRL1);
|
||||
reg_value |= XGMAC_USXG_EN;/*set USXG_EN*/
|
||||
if (priv->plat->interface == PHY_INTERFACE_MODE_10GKR)
|
||||
reg_value &= (~XGMAC_USXG_EN); /*Disable USXG_EN*/
|
||||
else
|
||||
reg_value |= XGMAC_USXG_EN; /*set USXG_EN*/
|
||||
|
||||
tc956x_xpcs_write(xpcsaddr, XGMAC_VR_XS_PCS_DIG_CTRL1, reg_value);
|
||||
|
||||
reg_value = tc956x_xpcs_read(xpcsaddr, XGMAC_VR_XS_PCS_KR_CTRL);
|
||||
@ -132,9 +141,9 @@ int tc956x_xpcs_init(struct tc956xmac_priv *priv, void __iomem *xpcsaddr)
|
||||
|
||||
reg_value = tc956x_xpcs_read(xpcsaddr, XGMAC_VR_MII_DIG_CTRL1);
|
||||
reg_value &= ~XGMAC_MAC_AUTO_SW_EN;/*MAC_AUTO_SW enable*/
|
||||
#ifndef TC956X_SGMII_2P5_GBPS_TEST
|
||||
reg_value |= XGMAC_MAC_AUTO_SW_EN;
|
||||
#endif
|
||||
if (priv->is_sgmii_2p5g != true)
|
||||
/* Enable only if SGMII 2.5G is not enabled. */
|
||||
reg_value |= XGMAC_MAC_AUTO_SW_EN;
|
||||
tc956x_xpcs_write(xpcsaddr, XGMAC_VR_MII_DIG_CTRL1, reg_value);
|
||||
|
||||
return 0;
|
||||
@ -144,15 +153,14 @@ void tc956x_xpcs_ctrl_ane(struct tc956xmac_priv *priv, bool ane)
|
||||
{
|
||||
u32 reg_value;
|
||||
|
||||
reg_value = tc956x_xpcs_read(priv->xpcsaddr, XGMAC_SR_MII_CTRL);
|
||||
if (ane) {
|
||||
reg_value = tc956x_xpcs_read(priv->xpcsaddr, XGMAC_SR_MII_CTRL);
|
||||
#ifndef TC956X_SGMII_2P5_GBPS_TEST
|
||||
reg_value |= XGMAC_AN_37_ENABLE;
|
||||
#else
|
||||
KPRINT_INFO("%s Enable AN", __func__);
|
||||
} else {
|
||||
reg_value &= (~XGMAC_AN_37_ENABLE);
|
||||
#endif
|
||||
tc956x_xpcs_write(priv->xpcsaddr, XGMAC_SR_MII_CTRL, reg_value);
|
||||
KPRINT_INFO("%s Disable AN", __func__);
|
||||
}
|
||||
|
||||
tc956x_xpcs_write(priv->xpcsaddr, XGMAC_SR_MII_CTRL, reg_value);
|
||||
}
|
||||
#endif
|
||||
|
@ -27,6 +27,10 @@
|
||||
*
|
||||
* 15 Mar 2021 : Base lined
|
||||
* VERSION : 01-00
|
||||
*
|
||||
* 05 Jul 2021 : 1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
* 2. XFI interface support and module parameters for selection of Port0 and Port1 interface
|
||||
* VERSION : 01-00-01
|
||||
*/
|
||||
|
||||
#ifndef __TC956X_XPCS_H__
|
||||
@ -77,7 +81,9 @@
|
||||
#define XPCS_REG_BASE_ADDR 10
|
||||
#define XPCS_REG_OFFSET 0x0003FF
|
||||
#define XPCS_IND_ACCESS 0x3FC
|
||||
|
||||
#define XPCS_SS_SGMII_1G 0x40
|
||||
#define XPCS_SS_SGMII_100M 0x2000
|
||||
#define XPCS_SS_SGMII_10M 0x0
|
||||
|
||||
u32 tc956x_xpcs_read(void __iomem *xpcsaddr, u32 pcs_reg_num);
|
||||
u32 tc956x_xpcs_write(void __iomem *xpcsaddr, u32 pcs_reg_num, u32 value);
|
||||
|
33
tc956xmac.h
33
tc956xmac.h
@ -30,6 +30,10 @@
|
||||
*
|
||||
* 15 Mar 2021 : Base lined
|
||||
* VERSION : 01-00
|
||||
*
|
||||
* 05 Jul 2021 : 1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
* 2. XFI interface support and module parameters for selection of Port0 and Port1 interface
|
||||
* VERSION : 01-00-01
|
||||
*/
|
||||
|
||||
#ifndef __TC956XMAC_H__
|
||||
@ -48,7 +52,7 @@
|
||||
#include <net/page_pool.h>
|
||||
#include <linux/version.h>
|
||||
|
||||
//#define TC956X_LOAD_FW_HEADER
|
||||
#define TC956X_LOAD_FW_HEADER
|
||||
#define PF_DRIVER 4
|
||||
|
||||
//#define DMA_OFFLOAD_ENABLE
|
||||
@ -77,7 +81,7 @@
|
||||
#ifdef TC956X
|
||||
|
||||
#define TC956X_RESOURCE_NAME "tc956x_pci-eth"
|
||||
#define DRV_MODULE_VERSION "V_01-00"
|
||||
#define DRV_MODULE_VERSION "V_01-00-01"
|
||||
#define TC956X_FW_MAX_SIZE (64*1024)
|
||||
|
||||
#define ATR_AXI4_SLV_BASE 0x0800
|
||||
@ -159,6 +163,14 @@
|
||||
/* Systick count SRAM address DMEM addrs 0x2000F83C, Check this value for any change */
|
||||
#define SYSTCIK_SRAM_OFFSET 0x4F83C
|
||||
|
||||
/* Tx Timer count SRAM address DMEM addrs 0x2000F844, Check this value for any change */
|
||||
#define TX_TIMER_SRAM_OFFSET_0 0x4F844
|
||||
|
||||
/* Tx Timer count SRAM address DMEM addrs 0x2000F848, Check this value for any change */
|
||||
#define TX_TIMER_SRAM_OFFSET_1 0x4F848
|
||||
|
||||
#define TX_TIMER_SRAM_OFFSET(t) (((t) == RM_PF0_ID) ? (TX_TIMER_SRAM_OFFSET_0) : (TX_TIMER_SRAM_OFFSET_1))
|
||||
|
||||
#define TC956X_M3_SRAM_EEPROM_MAC_ADDR 0x47000 /* DMEM addrs 0x20007000U */
|
||||
#define TC956X_M3_SRAM_EEPROM_OFFSET_ADDR 0x47050 /* DMEM addrs 0x20007050U */
|
||||
#define TC956X_M3_SRAM_EEPROM_MAC_COUNT 0x47051 /* DMEM addrs 0x20007051U */
|
||||
@ -168,15 +180,9 @@
|
||||
#define TC956X_M3_DBG_VER_START 0x4F900
|
||||
|
||||
#define ENABLE_USXGMII_INTERFACE 0
|
||||
#define ENABLE_RGMII_INTERFACE 1
|
||||
#define ENABLE_SGMII_INTERFACE 2
|
||||
|
||||
/* Only SGMII and USXGMII allowed for Port0 */
|
||||
#define PORT0_INTERFACE ENABLE_USXGMII_INTERFACE
|
||||
//#define PORT0_INTERFACE ENABLE_SGMII_INTERFACE
|
||||
#define PORT1_INTERFACE ENABLE_RGMII_INTERFACE
|
||||
|
||||
#define INTERFACE_SELECTED(p) (((p) == RM_PF0_ID) ? (PORT0_INTERFACE) : (PORT1_INTERFACE))
|
||||
#define ENABLE_XFI_INTERFACE 1 /* XFI/SFI, this is same as USXGMII, except XPCS autoneg disabled */
|
||||
#define ENABLE_RGMII_INTERFACE 2
|
||||
#define ENABLE_SGMII_INTERFACE 3
|
||||
|
||||
#define MTL_FPE_AFSZ_64 0
|
||||
#define MTL_FPE_AFSZ_128 1
|
||||
@ -200,6 +206,7 @@ struct tc956xmac_resources {
|
||||
int irq;
|
||||
#ifdef TC956X
|
||||
unsigned int port_num;
|
||||
unsigned int port_interface; /* Kernel module parameter variable for interface */
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -475,6 +482,8 @@ struct tc956xmac_priv {
|
||||
u32 port_num;
|
||||
u32 mac_loopback_mode;
|
||||
u32 phy_loopback_mode;
|
||||
bool is_sgmii_2p5g; /* For 2.5G SGMI, XPCS doesn't support AN. This flag is to identify 2.5G Speed for SGMII interface. */
|
||||
u32 port_interface; /* Kernel module parameter variable for interface */
|
||||
#endif
|
||||
|
||||
/* set to 1 when ptp offload is enabled, else 0. */
|
||||
@ -498,6 +507,8 @@ struct tc956x_version {
|
||||
unsigned char major;
|
||||
unsigned char minor;
|
||||
unsigned char sub_minor;
|
||||
unsigned char patch_rel_major;
|
||||
unsigned char patch_rel_minor;
|
||||
};
|
||||
|
||||
enum tc956xmac_state {
|
||||
|
@ -30,6 +30,10 @@
|
||||
*
|
||||
* 15 Mar 2021 : Base lined
|
||||
* VERSION : 01-00
|
||||
*
|
||||
* 05 Jul 2021 : 1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
* 2. XFI interface support and module parameters for selection of Port0 and Port1 interface
|
||||
* VERSION : 01-00-01
|
||||
*/
|
||||
|
||||
#include <linux/etherdevice.h>
|
||||
@ -588,7 +592,15 @@ static const struct tc956xmac_stats tc956xmac_gstrings_stats[] = {
|
||||
TC956XMAC_STAT(rxch_sw_dirty_rx[5]),
|
||||
TC956XMAC_STAT(rxch_sw_dirty_rx[6]),
|
||||
TC956XMAC_STAT(rxch_sw_dirty_rx[7]),
|
||||
|
||||
TC956XMAC_STAT(total_interrupts),
|
||||
TC956XMAC_STAT(lpi_intr_n),
|
||||
TC956XMAC_STAT(pmt_intr_n),
|
||||
TC956XMAC_STAT(event_intr_n),
|
||||
TC956XMAC_STAT(tx_intr_n),
|
||||
TC956XMAC_STAT(rx_intr_n),
|
||||
TC956XMAC_STAT(xpcs_intr_n),
|
||||
TC956XMAC_STAT(phy_intr_n),
|
||||
TC956XMAC_STAT(sw_msi_n),
|
||||
};
|
||||
#define TC956XMAC_STATS_LEN ARRAY_SIZE(tc956xmac_gstrings_stats)
|
||||
|
||||
@ -706,7 +718,7 @@ static void tc956xmac_ethtool_getdrvinfo(struct net_device *dev,
|
||||
#endif
|
||||
|
||||
fw_version = (struct tc956x_version *)(®);
|
||||
sprintf(fw_version_str, "Firmware Version %s_%d.%d-%d", (fw_version->rel_dbg == 'D')?"DBG":"REL",
|
||||
scnprintf(fw_version_str, sizeof(fw_version_str), "Firmware Version %s_%d.%d-%d", (fw_version->rel_dbg == 'D')?"DBG":"REL",
|
||||
fw_version->major, fw_version->minor,
|
||||
fw_version->sub_minor);
|
||||
|
||||
@ -849,7 +861,11 @@ tc956xmac_ethtool_set_link_ksettings(struct net_device *dev,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Temporary fix (phy dependent code): In case of AQR phy, auto negotiation OFF is not supported, return error for it */
|
||||
if (priv->port_num == RM_PF0_ID) {
|
||||
if (cmd->base.autoneg != AUTONEG_ENABLE)
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!dev->phydev)
|
||||
return -ENODEV;
|
||||
return phylink_ethtool_ksettings_set(priv->phylink, cmd);
|
||||
|
@ -30,6 +30,10 @@
|
||||
*
|
||||
* 15 Mar 2021 : Base lined
|
||||
* VERSION : 01-00
|
||||
*
|
||||
* 05 Jul 2021 : 1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
* 2. XFI interface support and module parameters for selection of Port0 and Port1 interface
|
||||
* VERSION : 01-00-01
|
||||
*/
|
||||
|
||||
#ifndef __TC956XMAC_PLATFORM_DATA
|
||||
@ -43,10 +47,16 @@
|
||||
//#define TC956X_IOCTL_REG_RD_WR_ENABLE
|
||||
//#define TC956X_WITHOUT_MDIO
|
||||
#define TC956X_PCIE_GEN3_SETTING
|
||||
//#define TC956X_SGMII_2P5_GBPS_TEST /*Enable this macro to test SGMII 2.5Gbps*/
|
||||
//#define TC956X_PCIE_DISABLE_DSP1 /*Enable this macro to disable DSP1 port*/
|
||||
//#define TC956X_PCIE_DISABLE_DSP2 /*Enable this macro to disable DSP2 port*/
|
||||
|
||||
/* Enable this macro to use Systick timer instead of Kernel timers
|
||||
* for handling Tx completion periodically
|
||||
*/
|
||||
#define TX_COMPLETION_WITHOUT_TIMERS
|
||||
#define TC956X_SW_MSI /*Enable this macro to process SW MSI when CM3 Systick Handler sends SW MSI*/
|
||||
//#define ENABLE_TX_TIMER /*Enable this macro to use Kernel timer. TC956X_SW_MSI can be disabled in this case */
|
||||
|
||||
/* By default macro is defined and code coverage this macro to be disabled */
|
||||
#define TC956X_UNSUPPORTED_UNTESTED_FEATURE
|
||||
|
||||
@ -280,5 +290,6 @@ struct plat_tc956xmacenet_data {
|
||||
enum ch_owner tx_dma_ch_owner[MTL_MAX_TX_QUEUES];
|
||||
enum ch_owner rx_dma_ch_owner[MTL_MAX_RX_QUEUES];
|
||||
u32 port_num;
|
||||
u32 port_interface; /* Kernel module parameter variable for interface */
|
||||
};
|
||||
#endif
|
||||
|
539
tc956xmac_main.c
539
tc956xmac_main.c
@ -30,6 +30,10 @@
|
||||
*
|
||||
* 15 Mar 2021 : Base lined
|
||||
* VERSION : 01-00
|
||||
*
|
||||
* 05 Jul 2021 : 1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
* 2. XFI interface support and module parameters for selection of Port0 and Port1 interface
|
||||
* VERSION : 01-00-01
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
@ -179,6 +183,98 @@ static uint16_t mdio_bus_id;
|
||||
#define CONFIG_PARAM_NUM ARRAY_SIZE(config_param_list)
|
||||
int tc956xmac_rx_parser_configuration(struct tc956xmac_priv *);
|
||||
|
||||
#ifdef DUMP_REGISTER
|
||||
void dump_registers(struct tc956xmac_priv *priv)
|
||||
{
|
||||
u32 i, j;
|
||||
|
||||
/* Register dump */
|
||||
printk("CNFREG dump\n");
|
||||
|
||||
for (i = 0; i <= 0x1800; i = i+4)
|
||||
printk("CNFREG 0x4000_%.4x = 0x%x\n", i, readl(priv->ioaddr + i));
|
||||
|
||||
printk("--------------------------------------------------------\n");
|
||||
printk("PMATOP register dump\n");
|
||||
|
||||
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x441b8, readl(priv->ioaddr + 0x441b8));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x45888, readl(priv->ioaddr + 0x45888));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x45890, readl(priv->ioaddr + 0x45890));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x45898, readl(priv->ioaddr + 0x45898));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x458a0, readl(priv->ioaddr + 0x458a0));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x458a8, readl(priv->ioaddr + 0x458a8));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x45080, readl(priv->ioaddr + 0x45080));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x45090, readl(priv->ioaddr + 0x45090));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x45094, readl(priv->ioaddr + 0x45094));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x450a4, readl(priv->ioaddr + 0x450a4));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x450a8, readl(priv->ioaddr + 0x450a8));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x450b8, readl(priv->ioaddr + 0x450b8));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x450bc, readl(priv->ioaddr + 0x450bc));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x450cc, readl(priv->ioaddr + 0x450cc));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x450d0, readl(priv->ioaddr + 0x450d0));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", 0x450e0, readl(priv->ioaddr + 0x450e0));
|
||||
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_GL_PM_CFG0, readl(priv->pmaaddr + XGMAC_PMA_GL_PM_CFG0));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_CFG_0_1_R0, readl(priv->pmaaddr + XGMAC_PMA_CFG_0_1_R0));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_CFG_0_1_R1, readl(priv->pmaaddr + XGMAC_PMA_CFG_0_1_R1));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_CFG_0_1_R2, readl(priv->pmaaddr + XGMAC_PMA_CFG_0_1_R2));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_CFG_0_1_R3, readl(priv->pmaaddr + XGMAC_PMA_CFG_0_1_R3));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_CFG_0_1_R4, readl(priv->pmaaddr + XGMAC_PMA_CFG_0_1_R4));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_HWT_REFCK_EN_R0, readl(priv->pmaaddr + XGMAC_PMA_HWT_REFCK_EN_R0));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_HWT_REFCK_TERM_EN_R0, readl(priv->pmaaddr + XGMAC_PMA_HWT_REFCK_TERM_EN_R0));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_HWT_REFCK_R_EN_R1, readl(priv->pmaaddr + XGMAC_PMA_HWT_REFCK_R_EN_R1));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_HWT_REFCK_TERM_EN_R1, readl(priv->pmaaddr + XGMAC_PMA_HWT_REFCK_TERM_EN_R1));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_HWT_REFCK_R_EN_R2, readl(priv->pmaaddr + XGMAC_PMA_HWT_REFCK_R_EN_R2));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_HWT_REFCK_TERM_EN_R2, readl(priv->pmaaddr + XGMAC_PMA_HWT_REFCK_TERM_EN_R2));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_HWT_REFCK_R_EN_R3, readl(priv->pmaaddr + XGMAC_PMA_HWT_REFCK_R_EN_R3));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_HWT_REFCK_TERM_EN_R3, readl(priv->pmaaddr + XGMAC_PMA_HWT_REFCK_TERM_EN_R3));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_HWT_REFCK_R_EN_R4, readl(priv->pmaaddr + XGMAC_PMA_HWT_REFCK_R_EN_R4));
|
||||
printk("PMATOP Reg 0x%x = 0x%x\n", XGMAC_PMA_HWT_REFCK_TERM_EN_R4, readl(priv->pmaaddr + XGMAC_PMA_HWT_REFCK_TERM_EN_R4));
|
||||
|
||||
printk("--------------------------------------------------------\n");
|
||||
printk("XPCS register dump\n");
|
||||
|
||||
printk("XPCS Reg 0x%x = 0x%x\n", XGMAC_SR_MII_CTRL, tc956x_xpcs_read(priv->xpcsaddr, XGMAC_SR_MII_CTRL));
|
||||
printk("XPCS Reg 0x%x = 0x%x\n", XGMAC_VR_MII_AN_CTRL, tc956x_xpcs_read(priv->xpcsaddr, XGMAC_VR_MII_AN_CTRL));
|
||||
printk("XPCS Reg 0x%x = 0x%x\n", XGMAC_VR_MII_DIG_CTRL1, tc956x_xpcs_read(priv->xpcsaddr, XGMAC_VR_MII_DIG_CTRL1));
|
||||
printk("XPCS Reg 0x%x = 0x%x\n", XGMAC_SR_XS_PCS_CTRL2, tc956x_xpcs_read(priv->xpcsaddr, XGMAC_SR_XS_PCS_CTRL2));
|
||||
printk("XPCS Reg 0x%x = 0x%x\n", XGMAC_VR_XS_PCS_DIG_CTRL1, tc956x_xpcs_read(priv->xpcsaddr, XGMAC_VR_XS_PCS_DIG_CTRL1));
|
||||
printk("XPCS Reg 0x%x = 0x%x\n", XGMAC_VR_XS_PCS_KR_CTRL, tc956x_xpcs_read(priv->xpcsaddr, XGMAC_VR_XS_PCS_KR_CTRL));
|
||||
printk("XPCS Reg 0x%x = 0x%x\n", XGMAC_VR_MII_AN_INTR_STS, tc956x_xpcs_read(priv->xpcsaddr, XGMAC_VR_MII_AN_INTR_STS));
|
||||
|
||||
printk("--------------------------------------------------------\n");
|
||||
|
||||
printk("XGMAC-MAC register dump\n");
|
||||
|
||||
for (i = 0; i <= 0x810; i = i+4)
|
||||
printk("XGMAC MAC Reg 0x400%.5x = 0x%x\n", MAC_OFFSET + i, readl(priv->ioaddr + MAC_OFFSET + i));
|
||||
|
||||
printk("--------------------------------------------------------\n");
|
||||
|
||||
printk("XGMAC-MTL register dump\n");
|
||||
for (i = 0x1000; i <= 0x10B4; i = i+4)
|
||||
printk("XGMAC MTL Reg 0x400%.5x = 0x%x\n", MAC_OFFSET + i, readl(priv->ioaddr + MAC_OFFSET + i));
|
||||
|
||||
for (i = 0x1100; i <= 0x1174; i = i+4) {
|
||||
for (j = 0; j < 2; j++)
|
||||
printk("XGMAC MTL Reg 0x400%.5x = 0x%x\n", MAC_OFFSET + i + (j*0x80), readl(priv->ioaddr + MAC_OFFSET + i + (j*0x80) ));
|
||||
}
|
||||
|
||||
printk("--------------------------------------------------------\n");
|
||||
|
||||
printk("XGMAC-DMA register dump\n");
|
||||
for (i = 0x3000; i <= 0x3084; i = i+4)
|
||||
printk("XGMAC DMA Reg 0x400%.5x = 0x%x\n", MAC_OFFSET + i, readl(priv->ioaddr + MAC_OFFSET + i));
|
||||
|
||||
for (i = 0x3100; i <= 0x317c; i = i+4) {
|
||||
for (j = 0; j < 2; j++)
|
||||
printk("XGMAC DMA Reg 0x400%.5x = 0x%x\n", MAC_OFFSET + i + (j*0x80), readl(priv->ioaddr + MAC_OFFSET + i + (j*0x80) ));
|
||||
}
|
||||
printk("--------------------------------------------------------\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* tc956xmac_verify_args - verify the driver parameters.
|
||||
* Description: it checks the driver parameters and set a default in case of
|
||||
@ -1156,7 +1252,8 @@ static void tc956xmac_mac_pcs_get_state(struct phylink_config *config,
|
||||
reg_value = tc956x_xpcs_read(priv->xpcsaddr, XGMAC_VR_MII_AN_INTR_STS);
|
||||
if (reg_value & XGMAC_C37_AN_COMPL) {/*check if AN 37 is complete CL37_ANCMPLT_INTR*/
|
||||
KPRINT_INFO("AN clause 37 completed");
|
||||
if (priv->plat->interface == PHY_INTERFACE_MODE_USXGMII) {
|
||||
if ((priv->plat->interface == PHY_INTERFACE_MODE_USXGMII) ||
|
||||
(priv->plat->interface == PHY_INTERFACE_MODE_10GKR)) {
|
||||
if (reg_value & XGMAC_USXG_AN_STS_LINK_MASK) {/*check link status*/
|
||||
state->link = 1;
|
||||
KPRINT_INFO("XPCS USXGMII link up");
|
||||
@ -1187,13 +1284,12 @@ static void tc956xmac_mac_pcs_get_state(struct phylink_config *config,
|
||||
else
|
||||
state->duplex = DUPLEX_HALF;
|
||||
|
||||
if (((reg_value & XGMAC_SGM_STS_SPEED_MASK) >> 2) == 0x2)/*SGMII autonegotiated speed */
|
||||
#ifndef TC956X_SGMII_2P5_GBPS_TEST
|
||||
state->speed = SPEED_1000;
|
||||
#else
|
||||
state->speed = SPEED_2500; /*There is no seperate bit check for 2.5Gbps, so set here */
|
||||
#endif
|
||||
else if (((reg_value & XGMAC_SGM_STS_SPEED_MASK) >> 2) == 0x1)
|
||||
if (((reg_value & XGMAC_SGM_STS_SPEED_MASK) >> 2) == 0x2) {/*SGMII autonegotiated speed */
|
||||
if (priv->is_sgmii_2p5g == true)
|
||||
state->speed = SPEED_2500; /*There is no seperate bit check for 2.5Gbps, so set here */
|
||||
else
|
||||
state->speed = SPEED_1000;
|
||||
} else if (((reg_value & XGMAC_SGM_STS_SPEED_MASK) >> 2) == 0x1)
|
||||
state->speed = SPEED_100;
|
||||
} else {
|
||||
state->link = 0;
|
||||
@ -1216,7 +1312,8 @@ static int tc956xmac_mac_link_state(struct phylink_config *config,
|
||||
reg_value = tc956x_xpcs_read(priv->xpcsaddr, XGMAC_VR_MII_AN_INTR_STS);
|
||||
if (reg_value & XGMAC_C37_AN_COMPL) {/*check if AN 37 is complete CL37_ANCMPLT_INTR*/
|
||||
KPRINT_INFO("AN clause 37 completed");
|
||||
if (priv->plat->interface == PHY_INTERFACE_MODE_USXGMII) {
|
||||
if ((priv->plat->interface == PHY_INTERFACE_MODE_USXGMII) ||
|
||||
(priv->plat->interface == PHY_INTERFACE_MODE_10GKR)) {
|
||||
if (reg_value & XGMAC_USXG_AN_STS_LINK_MASK) {/*check link status*/
|
||||
state->link = 1;
|
||||
KPRINT_INFO("XPCS USXGMII link up");
|
||||
@ -1251,15 +1348,12 @@ static int tc956xmac_mac_link_state(struct phylink_config *config,
|
||||
else
|
||||
state->duplex = DUPLEX_HALF;
|
||||
/*SGMII autonegotiated speed */
|
||||
if (((reg_value & XGMAC_SGM_STS_SPEED_MASK) >> 2) == 0x2)
|
||||
#ifndef TC956X_SGMII_2P5_GBPS_TEST
|
||||
state->speed = SPEED_1000;
|
||||
#else
|
||||
|
||||
/*There is no seperate bit check for 2.5Gbps, so set here */
|
||||
state->speed = SPEED_2500;
|
||||
#endif
|
||||
else if (((reg_value & XGMAC_SGM_STS_SPEED_MASK) >> 2) == 0x1)
|
||||
if (((reg_value & XGMAC_SGM_STS_SPEED_MASK) >> 2) == 0x2) {
|
||||
if (priv->is_sgmii_2p5g == true)
|
||||
state->speed = SPEED_2500; /*There is no seperate bit check for 2.5Gbps, so set here */
|
||||
else
|
||||
state->speed = SPEED_1000;
|
||||
} else if (((reg_value & XGMAC_SGM_STS_SPEED_MASK) >> 2) == 0x1)
|
||||
state->speed = SPEED_100;
|
||||
} else {
|
||||
state->link = 0;
|
||||
@ -1273,6 +1367,137 @@ static int tc956xmac_mac_link_state(struct phylink_config *config,
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* tc956xmac_speed_change_init_mac - Initialize MAC during speed change.
|
||||
* @priv: driver private structure
|
||||
* @state : phy state structure
|
||||
* Description: It is used for initializing MAC during speed change of
|
||||
* USXGMII and SGMII.
|
||||
*/
|
||||
void tc956xmac_speed_change_init_mac(struct tc956xmac_priv *priv,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
/* use signal from EMSPHY */
|
||||
uint8_t SgmSigPol = 0;
|
||||
int ret = 0;
|
||||
bool enable_an = true;
|
||||
|
||||
if (priv->port_num == RM_PF0_ID) {
|
||||
/* Enable all clocks to eMAC Port0 */
|
||||
ret = readl(priv->tc956x_SFR_pci_base_addr + NCLKCTRL0_OFFSET);
|
||||
if ((state->interface == PHY_INTERFACE_MODE_SGMII) &&
|
||||
(state->speed == SPEED_2500)) {
|
||||
ret &= ~NCLKCTRL0_MAC0125CLKEN;
|
||||
ret &= ~NCLKCTRL0_MAC0312CLKEN;
|
||||
}
|
||||
writel(ret, priv->tc956x_SFR_pci_base_addr + NCLKCTRL0_OFFSET);
|
||||
|
||||
/* Interface configuration for port0*/
|
||||
ret = readl(priv->tc956x_SFR_pci_base_addr + NEMAC0CTL_OFFSET);
|
||||
ret &= ~(NEMACCTL_SP_SEL_MASK | NEMACCTL_PHY_INF_SEL_MASK);
|
||||
if (state->interface == PHY_INTERFACE_MODE_SGMII) {
|
||||
if (state->speed == SPEED_2500)
|
||||
ret |= NEMACCTL_SP_SEL_SGMII_2500M;
|
||||
else
|
||||
ret |= NEMACCTL_SP_SEL_SGMII_1000M;
|
||||
}
|
||||
ret &= ~(0x00000040); /* Mask Polarity */
|
||||
if (SgmSigPol == 1)
|
||||
ret |= 0x00000040; /* Set Active low */
|
||||
ret |= (NEMACCTL_PHY_INF_SEL | NEMACCTL_LPIHWCLKEN);
|
||||
writel(ret, priv->tc956x_SFR_pci_base_addr + NEMAC0CTL_OFFSET);
|
||||
}
|
||||
if (priv->port_num == RM_PF1_ID) {
|
||||
/* Enable all clocks to eMAC Port1 */
|
||||
ret = readl(priv->tc956x_SFR_pci_base_addr + NCLKCTRL1_OFFSET);
|
||||
if ((state->interface == PHY_INTERFACE_MODE_SGMII) &&
|
||||
(state->speed == SPEED_2500)) {
|
||||
ret &= ~NCLKCTRL1_MAC1125CLKEN1;
|
||||
ret &= ~NCLKCTRL1_MAC1312CLKEN1;
|
||||
} else {
|
||||
ret &= ~NCLKCTRL1_MAC1312CLKEN1;
|
||||
ret |= NCLKCTRL1_MAC1125CLKEN1;
|
||||
}
|
||||
writel(ret, priv->tc956x_SFR_pci_base_addr + NCLKCTRL1_OFFSET);
|
||||
|
||||
/* Interface configuration for port1*/
|
||||
ret = readl(priv->tc956x_SFR_pci_base_addr + NEMAC1CTL_OFFSET);
|
||||
ret &= ~(NEMACCTL_SP_SEL_MASK | NEMACCTL_PHY_INF_SEL_MASK);
|
||||
if (state->interface == PHY_INTERFACE_MODE_SGMII) {
|
||||
if (state->speed == SPEED_2500)
|
||||
ret |= NEMACCTL_SP_SEL_SGMII_2500M;
|
||||
else
|
||||
ret |= NEMACCTL_SP_SEL_SGMII_1000M;
|
||||
}
|
||||
|
||||
ret &= ~(0x00000040); /* Mask Polarity */
|
||||
if (SgmSigPol == 1)
|
||||
ret |= 0x00000040; /* Set Active low */
|
||||
ret |= (NEMACCTL_PHY_INF_SEL | NEMACCTL_LPIHWCLKEN);
|
||||
writel(ret, priv->tc956x_SFR_pci_base_addr + NEMAC1CTL_OFFSET);
|
||||
}
|
||||
|
||||
/*PMA module init*/
|
||||
if (priv->hw->xpcs) {
|
||||
if (priv->port_num == RM_PF0_ID) {
|
||||
/* Assertion of PMA & XPCS reset software Reset*/
|
||||
ret = readl(priv->ioaddr + NRSTCTRL0_OFFSET);
|
||||
ret |= (NRSTCTRL0_MAC0PMARST | NRSTCTRL0_MAC0PONRST);
|
||||
writel(ret, priv->ioaddr + NRSTCTRL0_OFFSET);
|
||||
}
|
||||
if (priv->port_num == RM_PF1_ID) {
|
||||
/* Assertion of PMA & XPCS reset software Reset*/
|
||||
ret = readl(priv->ioaddr + NRSTCTRL1_OFFSET);
|
||||
ret |= (NRSTCTRL1_MAC1PMARST1 | NRSTCTRL1_MAC1PONRST1);
|
||||
writel(ret, priv->ioaddr + NRSTCTRL1_OFFSET);
|
||||
}
|
||||
|
||||
ret = tc956x_pma_setup(priv, priv->pmaaddr);
|
||||
if (ret < 0)
|
||||
KPRINT_ERR("PMA switching to internal clock Failed\n");
|
||||
|
||||
if (priv->port_num == RM_PF0_ID) {
|
||||
/* De-assertion of PMA & XPCS reset software Reset*/
|
||||
ret = readl(priv->ioaddr + NRSTCTRL0_OFFSET);
|
||||
ret &= ~(NRSTCTRL0_MAC0PMARST | NRSTCTRL0_MAC0PONRST);
|
||||
writel(ret, priv->ioaddr + NRSTCTRL0_OFFSET);
|
||||
}
|
||||
if (priv->port_num == RM_PF1_ID) {
|
||||
/* De-assertion of PMA & XPCS reset software Reset*/
|
||||
ret = readl(priv->ioaddr + NRSTCTRL1_OFFSET);
|
||||
ret &= ~(NRSTCTRL1_MAC1PMARST1 | NRSTCTRL1_MAC1PONRST1);
|
||||
writel(ret, priv->ioaddr + NRSTCTRL1_OFFSET);
|
||||
}
|
||||
|
||||
if (priv->port_num == RM_PF0_ID) {
|
||||
do {
|
||||
ret = readl(priv->ioaddr + NEMAC0CTL_OFFSET);
|
||||
} while ((NEMACCTL_INIT_DONE & ret) != NEMACCTL_INIT_DONE);
|
||||
}
|
||||
if (priv->port_num == RM_PF1_ID) {
|
||||
do {
|
||||
ret = readl(priv->ioaddr + NEMAC1CTL_OFFSET);
|
||||
} while ((NEMACCTL_INIT_DONE & ret) != NEMACCTL_INIT_DONE);
|
||||
}
|
||||
if ((state->interface == PHY_INTERFACE_MODE_SGMII)
|
||||
&& (state->speed == SPEED_2500)) {
|
||||
/* XPCS doesn't support AN for 2.5G SGMII.
|
||||
* Disable AN only if SGMII 2.5G is Enabled.
|
||||
*/
|
||||
priv->is_sgmii_2p5g = true;
|
||||
enable_an = false;
|
||||
} else {
|
||||
priv->is_sgmii_2p5g = false;
|
||||
enable_an = true;
|
||||
}
|
||||
|
||||
ret = tc956x_xpcs_init(priv, priv->xpcsaddr);
|
||||
if (ret < 0)
|
||||
KPRINT_INFO("XPCS initialization error\n");
|
||||
tc956x_xpcs_ctrl_ane(priv, enable_an);
|
||||
}
|
||||
}
|
||||
|
||||
static void tc956xmac_mac_config(struct phylink_config *config, unsigned int mode,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
@ -1330,34 +1555,53 @@ static void tc956xmac_mac_config(struct phylink_config *config, unsigned int mod
|
||||
val = tc956x_xpcs_read(priv->xpcsaddr, XGMAC_VR_XS_PCS_DIG_CTRL1);
|
||||
val |= XGMAC_USRA_RST;
|
||||
tc956x_xpcs_write(priv->xpcsaddr, XGMAC_VR_XS_PCS_DIG_CTRL1, val);
|
||||
|
||||
} else if (state->interface == PHY_INTERFACE_MODE_SGMII) {
|
||||
#if defined(TC956X) && defined(TC956X_SGMII_2P5_GBPS_TEST)
|
||||
/* Program autonegotiated speed to SR_MII_CTRL */
|
||||
val = tc956x_xpcs_read(priv->xpcsaddr, XGMAC_SR_MII_CTRL);
|
||||
val &= ~XGMAC_SR_MII_CTRL_SPEED; /* Mask speed ss13, ss6, ss5 */
|
||||
#endif
|
||||
|
||||
switch (state->speed) {
|
||||
case SPEED_2500:
|
||||
ctrl |= priv->hw->link.speed2500;
|
||||
#if defined(TC956X) && defined(TC956X_SGMII_2P5_GBPS_TEST)
|
||||
val |= 0x40; /*1000 Mbps setting only available, so set the same*/
|
||||
#endif
|
||||
emac_ctrl |= NEMACCTL_SP_SEL_SGMII_2500M;
|
||||
|
||||
break;
|
||||
case SPEED_1000:
|
||||
ctrl |= priv->hw->link.speed1000;
|
||||
emac_ctrl |= NEMACCTL_SP_SEL_SGMII_1000M;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
#if defined(TC956X) && defined(TC956X_SGMII_2P5_GBPS_TEST)
|
||||
tc956x_xpcs_write(priv->xpcsaddr, XGMAC_SR_MII_CTRL, val);
|
||||
#endif
|
||||
config_done = true;
|
||||
}
|
||||
}
|
||||
if (state->interface == PHY_INTERFACE_MODE_SGMII) { /* Autonegotiation not supported for SGMII */
|
||||
reg_value = tc956x_xpcs_read(priv->xpcsaddr, XGMAC_VR_MII_AN_INTR_STS);
|
||||
/* Clear autonegotiation only if completed. As for XPCS, 2.5G autonegotiation is not supported */
|
||||
/* Switching from SGMII 2.5G to any speed doesn't cause AN completion */
|
||||
if (reg_value & XGMAC_C37_AN_COMPL) {/*check if AN 37 is complete CL37_ANCMPLT_INTR*/
|
||||
KPRINT_INFO("AN clause 37 completed");
|
||||
reg_value &= ~(XGMAC_C37_AN_COMPL);
|
||||
tc956x_xpcs_write(priv->xpcsaddr, XGMAC_VR_MII_AN_INTR_STS, reg_value);
|
||||
KPRINT_INFO("AN clause 37 complete bit cleared");
|
||||
}
|
||||
/* Invoke this only during speed change */
|
||||
if ((state->speed != SPEED_UNKNOWN) || (state->speed != 0)) {
|
||||
if (state->speed != priv->speed) {
|
||||
tc956xmac_speed_change_init_mac(priv, state);
|
||||
}
|
||||
}
|
||||
val = tc956x_xpcs_read(priv->xpcsaddr, XGMAC_SR_MII_CTRL);
|
||||
val &= ~XGMAC_SR_MII_CTRL_SPEED; /* Mask speed ss13, ss6, ss5 */
|
||||
switch (state->speed) {
|
||||
case SPEED_2500:
|
||||
ctrl |= priv->hw->link.speed2500;
|
||||
/* Program autonegotiated speed to SR_MII_CTRL */
|
||||
val |= XPCS_SS_SGMII_1G; /*1000 Mbps setting only available, so set the same*/
|
||||
emac_ctrl |= NEMACCTL_SP_SEL_SGMII_2500M;
|
||||
break;
|
||||
case SPEED_1000:
|
||||
ctrl |= priv->hw->link.speed1000;
|
||||
val |= XPCS_SS_SGMII_1G; /*1000 Mbps setting only available, so set the same*/
|
||||
emac_ctrl |= NEMACCTL_SP_SEL_SGMII_1000M;
|
||||
break;
|
||||
case SPEED_100:
|
||||
ctrl |= priv->hw->link.speed100;
|
||||
val |= XPCS_SS_SGMII_100M; /*100 Mbps setting */
|
||||
emac_ctrl |= NEMACCTL_SP_SEL_SGMII_100M;
|
||||
break;
|
||||
case SPEED_10:
|
||||
ctrl |= priv->hw->link.speed10;
|
||||
val |= XPCS_SS_SGMII_10M; /*10 Mbps setting */
|
||||
emac_ctrl |= NEMACCTL_SP_SEL_SGMII_10M;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
tc956x_xpcs_write(priv->xpcsaddr, XGMAC_SR_MII_CTRL, val);
|
||||
config_done = true;
|
||||
}
|
||||
} else if (state->interface == PHY_INTERFACE_MODE_RGMII) {
|
||||
@ -1423,10 +1667,26 @@ static void tc956xmac_mac_an_restart(struct phylink_config *config)
|
||||
{
|
||||
#ifdef TC956X
|
||||
struct tc956xmac_priv *priv = netdev_priv(to_net_dev(config->dev));
|
||||
bool enable_en = true;
|
||||
|
||||
if (priv->hw->xpcs) {
|
||||
/*Enable XPCS Autoneg*/
|
||||
tc956x_xpcs_ctrl_ane(priv, 1);
|
||||
if (priv->plat->interface == PHY_INTERFACE_MODE_10GKR) {
|
||||
enable_en = false;
|
||||
KPRINT_INFO("%s :Port %d AN Enable:%d", __func__, priv->port_num, enable_en);
|
||||
} else if (priv->plat->interface == PHY_INTERFACE_MODE_SGMII) {
|
||||
if (priv->is_sgmii_2p5g == true) {
|
||||
enable_en = false;
|
||||
KPRINT_INFO("%s : Port %d AN Enable:%d", __func__, priv->port_num, enable_en);
|
||||
} else {
|
||||
enable_en = true;
|
||||
KPRINT_INFO("%s : Port %d AN Enable:%d", __func__, priv->port_num, enable_en);
|
||||
}
|
||||
} else {
|
||||
enable_en = true;
|
||||
KPRINT_INFO("%s : Port %d AN Enable:%d", __func__, priv->port_num, enable_en);
|
||||
}
|
||||
tc956x_xpcs_ctrl_ane(priv, enable_en);
|
||||
}
|
||||
#else
|
||||
/*Not supported*/
|
||||
@ -1498,8 +1758,9 @@ static void tc956xmac_check_pcs_mode(struct tc956xmac_priv *priv)
|
||||
#ifdef TC956X
|
||||
priv->hw->pcs = TC956XMAC_PCS_SGMII;
|
||||
#endif
|
||||
} else if (interface == PHY_INTERFACE_MODE_USXGMII) {
|
||||
netdev_dbg(priv->dev, "PCS USXGMII support enabled\n");
|
||||
} else if ((interface == PHY_INTERFACE_MODE_USXGMII) ||
|
||||
(interface == PHY_INTERFACE_MODE_10GKR)) {
|
||||
netdev_dbg(priv->dev, "PCS USXGMII/XFI support enabled\n");
|
||||
#ifdef TC956X
|
||||
priv->hw->pcs = TC956XMAC_PCS_USXGMII;
|
||||
#endif
|
||||
@ -1512,7 +1773,8 @@ static void tc956xmac_check_pcs_mode(struct tc956xmac_priv *priv)
|
||||
} else if (interface == PHY_INTERFACE_MODE_SGMII) {
|
||||
netdev_dbg(priv->dev, "PCS SGMII support enabled\n");
|
||||
priv->hw->xpcs = TC956XMAC_PCS_SGMII;
|
||||
} else if (interface == PHY_INTERFACE_MODE_USXGMII) {
|
||||
} else if ((interface == PHY_INTERFACE_MODE_USXGMII) ||
|
||||
(interface == PHY_INTERFACE_MODE_10GKR)) {
|
||||
netdev_dbg(priv->dev, "PCS USXGMII support enabled\n");
|
||||
priv->hw->xpcs = TC956XMAC_PCS_USXGMII;
|
||||
}
|
||||
@ -2661,10 +2923,11 @@ static int tc956xmac_tx_clean(struct tc956xmac_priv *priv, int budget, u32 queue
|
||||
mod_timer(&priv->eee_ctrl_timer, TC956XMAC_LPI_T(eee_timer));
|
||||
}
|
||||
|
||||
#ifdef ENABLE_TX_TIMER
|
||||
/* We still have pending packets, let's call for a new scheduling */
|
||||
if (tx_q->dirty_tx != tx_q->cur_tx)
|
||||
mod_timer(&tx_q->txtimer, TC956XMAC_COAL_TIMER(priv->tx_coal_timer));
|
||||
|
||||
#endif
|
||||
__netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue));
|
||||
|
||||
return count;
|
||||
@ -2808,6 +3071,11 @@ static int tc956xmac_napi_check(struct tc956xmac_priv *priv, u32 chan)
|
||||
|
||||
if ((status & handle_tx) && (chan < priv->plat->tx_queues_to_use) &&
|
||||
(priv->plat->tx_dma_ch_owner[chan] == USE_IN_TC956X_SW)) {
|
||||
|
||||
#ifdef TX_COMPLETION_WITHOUT_TIMERS
|
||||
writel(0, priv->tc956x_SRAM_pci_base_addr
|
||||
+ TX_TIMER_SRAM_OFFSET(priv->port_num));
|
||||
#endif
|
||||
if (napi_schedule_prep(&ch->tx_napi)) {
|
||||
spin_lock_irqsave(&ch->lock, flags);
|
||||
tc956xmac_disable_dma_irq(priv, priv->ioaddr, chan, 0, 1);
|
||||
@ -2999,6 +3267,7 @@ static int tc956xmac_init_dma_engine(struct tc956xmac_priv *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_TX_TIMER
|
||||
static void tc956xmac_tx_timer_arm(struct tc956xmac_priv *priv, u32 queue)
|
||||
{
|
||||
struct tc956xmac_tx_queue *tx_q = &priv->tx_queue[queue];
|
||||
@ -3037,6 +3306,8 @@ static void tc956xmac_tx_timer(struct timer_list *t)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* tc956xmac_init_coalesce - init mitigation options.
|
||||
* @priv: driver private structure
|
||||
@ -3047,13 +3318,15 @@ static void tc956xmac_tx_timer(struct timer_list *t)
|
||||
*/
|
||||
static void tc956xmac_init_coalesce(struct tc956xmac_priv *priv)
|
||||
{
|
||||
#ifdef ENABLE_TX_TIMER
|
||||
u32 tx_channel_count = priv->plat->tx_queues_to_use;
|
||||
u32 chan;
|
||||
|
||||
#endif
|
||||
priv->tx_coal_frames = TC956XMAC_TX_FRAMES;
|
||||
priv->tx_coal_timer = TC956XMAC_COAL_TX_TIMER;
|
||||
priv->rx_coal_frames = TC956XMAC_RX_FRAMES;
|
||||
|
||||
#ifdef ENABLE_TX_TIMER
|
||||
for (chan = 0; chan < tx_channel_count; chan++) {
|
||||
struct tc956xmac_tx_queue *tx_q = &priv->tx_queue[chan];
|
||||
|
||||
@ -3061,6 +3334,7 @@ static void tc956xmac_init_coalesce(struct tc956xmac_priv *priv)
|
||||
continue;
|
||||
timer_setup(&tx_q->txtimer, tc956xmac_tx_timer, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void tc956xmac_set_rings_length(struct tc956xmac_priv *priv)
|
||||
@ -3336,6 +3610,7 @@ static int tc956xmac_hw_setup(struct net_device *dev, bool init_ptp)
|
||||
struct tc956xmac_priv *priv = netdev_priv(dev);
|
||||
#ifdef TC956X
|
||||
u32 rx_cnt = priv->plat->rx_queues_to_use;
|
||||
bool enable_en = true;
|
||||
#endif
|
||||
|
||||
u32 tx_cnt = priv->plat->tx_queues_to_use;
|
||||
@ -3428,9 +3703,19 @@ static int tc956xmac_hw_setup(struct net_device *dev, bool init_ptp)
|
||||
}
|
||||
|
||||
#ifdef TC956X
|
||||
if (priv->hw->xpcs)
|
||||
if (priv->hw->xpcs) {
|
||||
/*C37 AN enable*/
|
||||
tc956x_xpcs_ctrl_ane(priv, 1);
|
||||
if (priv->plat->interface == PHY_INTERFACE_MODE_10GKR)
|
||||
enable_en = false;
|
||||
else if (priv->plat->interface == PHY_INTERFACE_MODE_SGMII) {
|
||||
if (priv->is_sgmii_2p5g == true)
|
||||
enable_en = false;
|
||||
else
|
||||
enable_en = true;
|
||||
} else
|
||||
enable_en = true;
|
||||
tc956x_xpcs_ctrl_ane(priv, enable_en);
|
||||
}
|
||||
#else
|
||||
if (priv->hw->pcs)
|
||||
tc956xmac_pcs_ctrl_ane(priv, priv->ioaddr, 1, priv->hw->ps, 0);
|
||||
@ -3625,8 +3910,21 @@ static int tc956xmac_open(struct net_device *dev)
|
||||
rd_val |= (1 << (MSI_INT_RX_CH0 + chan));
|
||||
}
|
||||
|
||||
/* PHY MSI interrupt diabled */
|
||||
rd_val |= (1 << MSI_INT_EXT_PHY);
|
||||
|
||||
/* Disable MAC Event and XPCS interrupt */
|
||||
rd_val = ENABLE_MSI_INTR & (~rd_val);
|
||||
|
||||
#ifdef TC956X_SW_MSI
|
||||
/* Enable SW MSI interrupt */
|
||||
KPRINT_INFO("%s Enable SW MSI", __func__);
|
||||
rd_val |= (1 << MSI_INT_SW_MSI);
|
||||
|
||||
/*Clear SW MSI*/
|
||||
writel(1, priv->ioaddr + TC956X_MSI_SW_MSI_CLR(priv->port_num));
|
||||
|
||||
#endif
|
||||
writel(rd_val, priv->ioaddr + TC956X_MSI_OUT_EN_OFFSET(priv->port_num)); /* MSI_OUT_EN: Enable All mac int */
|
||||
|
||||
#endif
|
||||
@ -3688,8 +3986,13 @@ static int tc956xmac_open(struct net_device *dev)
|
||||
|
||||
/* MSI_MASK_CLR: unmask vector 0 */
|
||||
writel(0x00000001, priv->ioaddr + TC956X_MSI_MASK_CLR_OFFSET(priv->port_num));
|
||||
|
||||
#ifdef TX_COMPLETION_WITHOUT_TIMERS
|
||||
writel(0, priv->tc956x_SRAM_pci_base_addr
|
||||
+ TX_TIMER_SRAM_OFFSET(priv->port_num));
|
||||
#endif
|
||||
|
||||
#endif
|
||||
return 0;
|
||||
#ifndef TC956X
|
||||
lpiirq_error:
|
||||
@ -3700,12 +4003,12 @@ static int tc956xmac_open(struct net_device *dev)
|
||||
#endif
|
||||
irq_error:
|
||||
phylink_stop(priv->phylink);
|
||||
|
||||
#ifdef ENABLE_TX_TIMER
|
||||
for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++) {
|
||||
if (priv->plat->tx_dma_ch_owner[chan] == USE_IN_TC956X_SW)
|
||||
del_timer_sync(&priv->tx_queue[chan].txtimer);
|
||||
}
|
||||
|
||||
#endif
|
||||
tc956xmac_hw_teardown(dev);
|
||||
init_error:
|
||||
free_dma_desc_resources(priv);
|
||||
@ -3723,8 +4026,14 @@ static int tc956xmac_open(struct net_device *dev)
|
||||
static int tc956xmac_release(struct net_device *dev)
|
||||
{
|
||||
struct tc956xmac_priv *priv = netdev_priv(dev);
|
||||
#ifdef ENABLE_TX_TIMER
|
||||
u32 chan;
|
||||
#endif
|
||||
|
||||
#ifdef TX_COMPLETION_WITHOUT_TIMERS
|
||||
writel(0, priv->tc956x_SRAM_pci_base_addr
|
||||
+ TX_TIMER_SRAM_OFFSET(priv->port_num));
|
||||
#endif
|
||||
if (priv->eee_enabled)
|
||||
del_timer_sync(&priv->eee_ctrl_timer);
|
||||
|
||||
@ -3736,12 +4045,12 @@ static int tc956xmac_release(struct net_device *dev)
|
||||
tc956xmac_stop_all_queues(priv);
|
||||
|
||||
tc956xmac_disable_all_queues(priv);
|
||||
|
||||
#ifdef ENABLE_TX_TIMER
|
||||
for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++) {
|
||||
if (priv->plat->tx_dma_ch_owner[chan] == USE_IN_TC956X_SW)
|
||||
del_timer_sync(&priv->tx_queue[chan].txtimer);
|
||||
}
|
||||
|
||||
#endif
|
||||
/* Free the IRQ lines */
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
@ -4109,8 +4418,14 @@ static netdev_tx_t tc956xmac_tso_xmit(struct sk_buff *skb, struct net_device *de
|
||||
|
||||
tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * desc_size);
|
||||
tc956xmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
|
||||
#ifdef ENABLE_TX_TIMER
|
||||
tc956xmac_tx_timer_arm(priv, queue);
|
||||
#endif
|
||||
|
||||
#ifdef TX_COMPLETION_WITHOUT_TIMERS
|
||||
writel(1, priv->tc956x_SRAM_pci_base_addr
|
||||
+ TX_TIMER_SRAM_OFFSET(priv->port_num));
|
||||
#endif
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
dma_map_err:
|
||||
@ -4446,7 +4761,15 @@ static netdev_tx_t tc956xmac_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
|
||||
tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * desc_size);
|
||||
tc956xmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
|
||||
|
||||
#ifdef ENABLE_TX_TIMER
|
||||
tc956xmac_tx_timer_arm(priv, queue);
|
||||
#endif
|
||||
|
||||
#ifdef TX_COMPLETION_WITHOUT_TIMERS
|
||||
writel(1, priv->tc956x_SRAM_pci_base_addr
|
||||
+ TX_TIMER_SRAM_OFFSET(priv->port_num));
|
||||
#endif
|
||||
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
@ -5052,6 +5375,34 @@ static irqreturn_t tc956xmac_interrupt(int irq, void *dev_id)
|
||||
if (tc956xmac_safety_feat_interrupt(priv))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
val = readl(priv->ioaddr + TC956X_MSI_INT_STS_OFFSET(priv->port_num));
|
||||
|
||||
priv->xstats.total_interrupts++;
|
||||
|
||||
if (val & (1 << 0))
|
||||
priv->xstats.lpi_intr_n++;
|
||||
|
||||
if (val & (1 << 1))
|
||||
priv->xstats.pmt_intr_n++;
|
||||
|
||||
if (val & (1 << 2))
|
||||
priv->xstats.event_intr_n++;
|
||||
|
||||
if (val & (0xFF << 3))
|
||||
priv->xstats.tx_intr_n++;
|
||||
|
||||
if (val & (0xFF << 11))
|
||||
priv->xstats.rx_intr_n++;
|
||||
|
||||
if (val & (1 << 19))
|
||||
priv->xstats.xpcs_intr_n++;
|
||||
|
||||
if (val & (1 << 20))
|
||||
priv->xstats.phy_intr_n++;
|
||||
|
||||
if (val & (1 << 24))
|
||||
priv->xstats.sw_msi_n++;
|
||||
|
||||
/* To handle GMAC own interrupts */
|
||||
if ((priv->plat->has_gmac) || xmac) {
|
||||
int status = tc956xmac_host_irq_status(priv, priv->hw, &priv->xstats);
|
||||
@ -5094,6 +5445,19 @@ static irqreturn_t tc956xmac_interrupt(int irq, void *dev_id)
|
||||
val = readl(priv->ioaddr + TC956X_MSI_INT_STS_OFFSET(priv->port_num));
|
||||
if (val & TC956X_EXT_PHY_ETH_INT)
|
||||
phy_mac_interrupt(priv->dev->phydev);
|
||||
#ifdef TC956X_SW_MSI
|
||||
if (val & TC956X_SW_MSI_INT) {
|
||||
//DBGPR_FUNC(priv->device, "%s SW MSI INT STS[%08x]\n", __func__, val);
|
||||
|
||||
/*Clear SW MSI*/
|
||||
writel(1, priv->ioaddr + TC956X_MSI_SW_MSI_CLR(priv->port_num));
|
||||
|
||||
val = readl(priv->ioaddr + TC956X_MSI_SW_MSI_CLR(priv->port_num));
|
||||
|
||||
//DBGPR_FUNC(priv->device, "%s SW MSI INT CLR[%08x]\n", __func__, val);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TC956X
|
||||
/* MSI_MSK_CLR, unmask vector 0 */
|
||||
@ -9092,30 +9456,6 @@ static unsigned char tc956x_get_rx_channel_count(struct tc956xmac_resources *res
|
||||
#endif
|
||||
#ifndef EEPROM_MAC_ADDR
|
||||
|
||||
/*!
|
||||
* \brief API to kernel read from file
|
||||
*
|
||||
* \param[in] file - pointer to file descriptor
|
||||
* \param[in] offset - Offset of file to start read
|
||||
* \param[in] size - Size of the buffer to be read
|
||||
*
|
||||
* \param[out] data - File data buffer
|
||||
*
|
||||
*
|
||||
* \return integer
|
||||
*
|
||||
* \retval 0 on success & -ve number on failure.
|
||||
*/
|
||||
static int file_read(struct file *file, unsigned long long offset,
|
||||
unsigned char *data, unsigned int size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = kernel_read(file, (void *)data, size, &offset);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief API to validate MAC ID
|
||||
*
|
||||
@ -9273,29 +9613,24 @@ static bool lookfor_macid(char *file_buf)
|
||||
*/
|
||||
static void parse_config_file(void)
|
||||
{
|
||||
struct file *filep = NULL;
|
||||
char *data = kmalloc(1000, GFP_KERNEL);
|
||||
int ret, flags = O_RDONLY, i = 0;
|
||||
mm_segment_t oldfs;
|
||||
void *data;
|
||||
char *cdata;
|
||||
int ret, i;
|
||||
loff_t size;
|
||||
|
||||
KPRINT_INFO("-->%s", __func__);
|
||||
oldfs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
filep = filp_open("config.ini", flags, 0600);
|
||||
set_fs(oldfs);
|
||||
if (IS_ERR(filep)) {
|
||||
ret = kernel_read_file_from_path("config.ini", &data, &size, 1000, READING_POLICY);
|
||||
|
||||
if (ret < 0) {
|
||||
KPRINT_ERR("Mac configuration file not found\n");
|
||||
KPRINT_INFO("Using Default MAC Address\n");
|
||||
return;
|
||||
} else {
|
||||
cdata = data;
|
||||
/* Parse the file */
|
||||
ret = file_read(filep, 0, data, 1000);
|
||||
for (i = 0; i < CONFIG_PARAM_NUM; i++) {
|
||||
if (strstr((const char *)data, config_param_list[i]
|
||||
.mdio_key)) {
|
||||
if (strstr((const char *)cdata, config_param_list[i].mdio_key)) {
|
||||
KPRINT_DEBUG1("Pattern Match\n");
|
||||
if (strncmp(config_param_list[i].mdio_key,
|
||||
"MDIOBUSID", 9) == 0) {
|
||||
if (strncmp(config_param_list[i].mdio_key, "MDIOBUSID", 9) == 0) {
|
||||
/* MAC ID Configuration */
|
||||
KPRINT_DEBUG1("MAC_ID Configuration\n");
|
||||
lookfor_macid(data);
|
||||
@ -9304,10 +9639,11 @@ static void parse_config_file(void)
|
||||
}
|
||||
}
|
||||
|
||||
kfree(data);
|
||||
filp_close(filep, NULL);
|
||||
vfree(data);
|
||||
KPRINT_INFO("<--%s", __func__);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -9383,11 +9719,14 @@ int tc956xmac_dvr_probe(struct device *device,
|
||||
#endif
|
||||
priv->port_num = res->port_num;
|
||||
priv->dev->base_addr = (unsigned long)res->addr;
|
||||
|
||||
if (priv->plat->interface == PHY_INTERFACE_MODE_SGMII)
|
||||
priv->is_sgmii_2p5g = true;
|
||||
else
|
||||
priv->is_sgmii_2p5g = false;
|
||||
priv->dev->irq = res->irq;
|
||||
priv->wol_irq = res->wol_irq;
|
||||
priv->lpi_irq = res->lpi_irq;
|
||||
|
||||
priv->port_interface = res->port_interface;
|
||||
#ifdef DMA_OFFLOAD_ENABLE
|
||||
priv->client_priv = NULL;
|
||||
#endif
|
||||
|
@ -30,6 +30,10 @@
|
||||
*
|
||||
* 15 Mar 2021 : Base lined
|
||||
* VERSION : 01-00
|
||||
*
|
||||
* 05 Jul 2021 : 1. Used Systick handler instead of Driver kernel timer to process transmitted Tx descriptors.
|
||||
* 2. XFI interface support and module parameters for selection of Port0 and Port1 interface
|
||||
* VERSION : 01-00-01
|
||||
*/
|
||||
|
||||
#include <linux/gpio/consumer.h>
|
||||
@ -61,7 +65,7 @@
|
||||
#define MII_XGMAC_WRITE (1 << MII_XGMAC_CMD_SHIFT)
|
||||
#define MII_XGMAC_READ (3 << MII_XGMAC_CMD_SHIFT)
|
||||
#define MII_XGMAC_BUSY BIT(22)
|
||||
#define MII_XGMAC_MAX_C22ADDR 3
|
||||
#define MII_XGMAC_MAX_C22ADDR 31
|
||||
#define MII_XGMAC_C22P_MASK GENMASK(MII_XGMAC_MAX_C22ADDR, 0)
|
||||
#define MII_XGMAC_PA_SHIFT 16
|
||||
#define MII_XGMAC_DA_SHIFT 21
|
||||
@ -88,13 +92,8 @@ static int tc956xmac_xgmac2_c22_format(struct tc956xmac_priv *priv, int phyaddr,
|
||||
{
|
||||
u32 tmp;
|
||||
|
||||
/* HW does not support C22 addr >= 4 */
|
||||
if (phyaddr > MII_XGMAC_MAX_C22ADDR)
|
||||
return -ENODEV;
|
||||
|
||||
/* Set port as Clause 22 */
|
||||
tmp = readl(priv->ioaddr + XGMAC_MDIO_C22P);
|
||||
tmp &= ~MII_XGMAC_C22P_MASK;
|
||||
tmp |= BIT(phyaddr);
|
||||
writel(tmp, priv->ioaddr + XGMAC_MDIO_C22P);
|
||||
|
||||
@ -494,9 +493,12 @@ int tc956xmac_mdio_register(struct net_device *ndev)
|
||||
|
||||
if (phy_reg_read != -EBUSY) {
|
||||
if (phy_reg_read != 0x0000 && phy_reg_read != 0xffff) {
|
||||
NMSGPR_ALERT(priv->device,
|
||||
if (priv->plat->c45_needed == true)
|
||||
NMSGPR_ALERT(priv->device,
|
||||
"TC956X: Phy detected C45 at ID/ADDR %d\n", addr);
|
||||
else
|
||||
NMSGPR_ALERT(priv->device,
|
||||
"TC956X: Phy detected C22 at ID/ADDR %d\n", addr);
|
||||
|
||||
#else
|
||||
struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user