V_01-00-42

1. Reset assert and clock disable support during Link Down.
This commit is contained in:
TC956X 2022-02-15 00:26:13 +09:00 committed by jianzhou
parent 4d94d05dd1
commit ffcc08ecdb
5 changed files with 162 additions and 9 deletions

View file

@ -1,7 +1,7 @@
# Toshiba Electronic Devices & Storage Corporation TC956X PCIe Ethernet Host Driver
Release Date: 04 Feb 2022
Release Date: 14 Feb 2022
Release Version: V_01-00-41 : Limited-tested version
Release Version: V_01-00-42 : Limited-tested version
TC956X PCIe EMAC driver is based on "Fedora 30, kernel-5.4.19".
@ -459,3 +459,7 @@ TC956X PCIe EMAC driver is based on "Fedora 30, kernel-5.4.19".
1. DMA channel status cleared only for SW path allocated DMA channels. IPA path DMA channel status clearing is skipped.
2. Ethtool statistics added to print doorbell SRAM area for all the channels.
## TC956X_Host_Driver_20220214_V_01-00-42:
1. Reset assert and clock disable support during Link Down.

View file

@ -76,7 +76,9 @@
* 31 Jan 2022 : 1. Additional macros defined for debug dump API usage.
* VERSION : 01-00-39
* 04 Feb 2021 : 1. Ethtool statistics added to print doorbell SRAM area for all the channels.
* VERSION : 01-00-41
* VERSION : 01-00-41
* 14 Feb 2021 : 1. Reset assert and clock disable support during Link Down.
* VERSION : 01-00-42
*/
#ifndef __COMMON_H__
@ -108,12 +110,19 @@
#define TC956X_MAX_PORT 2
#define TC956X_ALL_MAC_PORT_SUSPENDED 0 /* All EMAC Port Suspended. To be used just after suspend and before resume. */
#define TC956X_NO_MAC_DEVICE_IN_USE 0 /* No EMAC Port in use. To be used at probe and remove. */
#define TC956X_ALL_MAC_PORT_LINK_DOWN 2 /* All ports are Link Down */
/* Suspend-Resume Arguments */
enum TC956X_PORT_PM_STATE {
SUSPEND = 0,
RESUME,
};
/* Link Down Change Power State Arguments */
enum TC956X_PORT_LINK_CHANGE_STATE {
LINK_DOWN = 0,
LINK_UP,
};
//#define TC956X_PCIE_LINK_STATE_LATENCY_CTRL
#define DISABLE 0
@ -730,6 +739,16 @@ enum packets_types {
#define NCLKCTRL0_DEFAULT (NCLKCTRL0_SRMCEM | NCLKCTRL0_I2SSPIEN | \
NCLKCTRL0_PCIECEN | NCLKCTRL0_MCUCEN)
#define NBUSCTRL_OFFSET (0x1014)
#define NRSTCTRL_LINK_DOWN (NRSTCTRL0_MAC0PMARST | NRSTCTRL0_MAC0PONRST)
#define NCLKCTRL_LINK_DOWN (NCLKCTRL0_MAC0TXCEN | NCLKCTRL0_MAC0RXCEN | \
NCLKCTRL0_MAC0125CLKEN | NCLKCTRL0_MAC0312CLKEN | \
NCLKCTRL1_MAC1RMCEN)
#define NRSTCTRL_LINK_DOWN_SAVE (0xC0000080U) /* Save Non-Common Reset Register Bits Between Port 0 and Port 1 */
#define NCLKCTRL_LINK_DOWN_SAVE (0xE000C080U) /* Save Non-Common Clock Register Bits Between Port 0 and Port 1 */
#define NRSTCTRL_LINK_DOWN_CMN_SAVE (0x00051213U) /* Save Common Reset Register Bits Between Port 0 and Port 1 */
#define NCLKCTRL_LINK_DOWN_CMN_SAVE (0x07053211U) /* Save Common Clock Register Bits Between Port 0 and Port 1 */
#endif
#define NSPLLPARAM_OFFSET (0x1020) /* TC956X System PLL parameters */

View file

@ -140,6 +140,8 @@
* VERSION : 01-00-40
* 04 Feb 2022 : 1. Version update
* VERSION : 01-00-41
* 14 Feb 2022 : 1. Version update
* VERSION : 01-00-42
*/
#include <linux/clk-provider.h>
@ -204,7 +206,7 @@ static unsigned int mac1_txq1_size = TX_QUEUE1_SIZE;
unsigned int mac0_en_lp_pause_frame_cnt = DISABLE;
unsigned int mac1_en_lp_pause_frame_cnt = DISABLE;
static const struct tc956x_version tc956x_drv_version = {0, 1, 0, 0, 4, 1};
static const struct tc956x_version tc956x_drv_version = {0, 1, 0, 0, 4, 2};
static int tc956xmac_pm_usage_counter; /* Device Usage Counter */
struct mutex tc956x_pm_suspend_lock; /* This mutex is shared between all available EMAC ports. */

View file

@ -129,6 +129,9 @@
* VERSION : 01-00-40
* 04 Feb 2022 : 1. Version update
* VERSION : 01-00-41
* 14 Feb 2022 : 1. Reset assert and clock disable support during Link Down.
* 2. Version update.
* VERSION : 01-00-42
*/
#ifndef __TC956XMAC_H__
@ -184,7 +187,7 @@
#define IRQ_DEV_NAME(x) (((x) == RM_PF0_ID) ? ("eth0") : ("eth1"))
#define WOL_IRQ_DEV_NAME(x) (((x) == RM_PF0_ID) ? ("eth0_wol") : ("eth1_wol"))
#define DRV_MODULE_VERSION "V_01-00-41"
#define DRV_MODULE_VERSION "V_01-00-42"
#define TC956X_FW_MAX_SIZE (64*1024)
#define ATR_AXI4_SLV_BASE 0x0800
@ -662,7 +665,9 @@ struct tc956xmac_priv {
struct work_struct emac_phy_work;
u32 pm_saved_emac_rst; /* Save and restore EMAC Resets during suspend-resume sequence */
u32 pm_saved_emac_clk; /* Save and restore EMAC Clocks during suspend-resume sequence */
u32 pm_saved_linkdown_rst; /* Save and restore Resets during link-down sequence */
u32 pm_saved_linkdown_clk; /* Save and restore Clocks during link-down sequence */
bool port_link_down; /* Flag to save per port link down state */
};
struct tc956x_version {

View file

@ -105,6 +105,8 @@
* VERSION : 01-00-39
* 04 Feb 2022 : 1. DMA channel status cleared only for SW path allocated DMA channels. IPA path DMA channel status clearing is skipped.
* VERSION : 01-00-41
* 14 Feb 2022 : 1. Reset assert and clock disable support during Link Down.
* VERSION : 01-00-42
*/
#include <linux/clk.h>
@ -218,6 +220,9 @@ static void tc956xmac_init_fs(struct net_device *dev);
static void tc956xmac_exit_fs(struct net_device *dev);
#endif
static u32 tc956xmac_link_down_counter = 0; /* Counter to count Link Down/Up for both port */
static void tc956xmac_link_change_set_power(struct tc956xmac_priv *priv, enum TC956X_PORT_LINK_CHANGE_STATE state);
#define TC956XMAC_COAL_TIMER(x) (jiffies + usecs_to_jiffies(x))
/* MAC address */
@ -2383,6 +2388,9 @@ static void tc956xmac_mac_link_down(struct phylink_config *config,
#ifdef TC956X_PM_DEBUG
pm_generic_suspend(priv->device);
#endif
tc956xmac_link_down_counter++; /* Increment counter only when Link Down */
tc956xmac_link_change_set_power(priv, LINK_DOWN); /* Save, Assert and Disable Reset and Clock */
priv->port_link_down = true; /* Set per port flag to true */
}
#ifdef TC956X_5_G_2_5_G_EEE_SUPPORT
@ -2593,6 +2601,9 @@ static void tc956xmac_mac_link_up(struct phylink_config *config,
{
struct tc956xmac_priv *priv = netdev_priv(to_net_dev(config->dev));
if (priv->port_link_down == true)
tc956xmac_link_change_set_power(priv, LINK_UP); /* Restore, De-assert and Enable Reset and Clock */
tc956xmac_mac_set_rx(priv, priv->ioaddr, true);
#ifdef EEE
if (phy && priv->dma_cap.eee && priv->eee_enabled) {
@ -4811,7 +4822,11 @@ static int tc956xmac_open(struct net_device *dev)
KPRINT_INFO("---> %s : Port %d", __func__, priv->port_num);
phydev = mdiobus_get_phy(priv->mii, addr);
if (priv->port_link_down == true) {
tc956xmac_link_change_set_power(priv, LINK_UP); /* Restore, De-assert and Enable Reset and Clock */
}
if (!phydev) {
netdev_err(priv->dev, "no phy at addr %d\n", addr);
return -ENODEV;
@ -6587,6 +6602,10 @@ 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) {
KPRINT_INFO("PHY Interrupt %s \n", __func__);
if (priv->port_link_down == true)
tc956xmac_link_change_set_power(priv, LINK_UP); /* Restore, De-assert and Enable Reset and Clock */
/* Queue the work in system_wq */
if (priv->tc956x_port_pm_suspend == true) {
KPRINT_INFO("%s : (Do not queue PHY Work during suspend. Set WOL Interrupt flag) \n", __func__);
@ -10956,7 +10975,9 @@ int tc956xmac_dvr_probe(struct device *device,
priv->port_interface = res->port_interface;
priv->eee_enabled = res->eee_enabled;
priv->tx_lpi_timer = res->tx_lpi_timer;
priv->pm_saved_linkdown_rst = 0;
priv->pm_saved_linkdown_clk = 0;
priv->port_link_down = false;
#ifdef DMA_OFFLOAD_ENABLE
priv->client_priv = NULL;
memset(priv->cm3_tamap, 0, sizeof(struct tc956xmac_cm3_tamap) * MAX_CM3_TAMAP_ENTRIES);
@ -11611,6 +11632,108 @@ clean_exit:
}
EXPORT_SYMBOL_GPL(tc956xmac_resume);
/*!
* \brief API to save and restore clock and reset during link down and link up.
*
* \details This fucntion saves the EMAC clock and reset bits before
* link down. And restores the same settings after link up.
*
* \param[in] priv - pointer to device private structure.
* \param[in] state - identify LINK DOWN and LINK DOWN operation.
*
* \return None
*/
static void tc956xmac_link_change_set_power(struct tc956xmac_priv *priv, enum TC956X_PORT_LINK_CHANGE_STATE state)
{
void *nrst_reg = NULL, *nclk_reg = NULL, *commonrst_reg = NULL, *commonclk_reg = NULL;
u32 nrst_val = 0, nclk_val = 0, commonrst_val = 0, commonclk_val = 0;
static u32 pm_saved_cmn_linkdown_rst = 0, pm_saved_cmn_linkdown_clk = 0;
KPRINT_INFO("-->%s : Port %d", __func__, priv->port_num);
/* Select register address by port */
if (priv->port_num == 0) {
nrst_reg = priv->tc956x_SFR_pci_base_addr + NRSTCTRL0_OFFSET;
nclk_reg = priv->tc956x_SFR_pci_base_addr + NCLKCTRL0_OFFSET;
} else {
nrst_reg = priv->tc956x_SFR_pci_base_addr + NRSTCTRL1_OFFSET;
nclk_reg = priv->tc956x_SFR_pci_base_addr + NCLKCTRL1_OFFSET;
}
if (state == LINK_DOWN) {
KPRINT_INFO("%s : Port %d Set Power for Link Down", __func__, priv->port_num);
nrst_val = readl(nrst_reg);
nclk_val = readl(nclk_reg);
KPRINT_INFO("%s : Port %d Rd RST Reg:%x, CLK Reg:%x", __func__, priv->port_num,
nrst_val, nclk_val);
/* Save register values before Asserting reset and Clock Disable */
priv->pm_saved_linkdown_rst = ((~nrst_val) & NRSTCTRL_LINK_DOWN_SAVE); /* Save Non-Common De-Asserted Resets */
priv->pm_saved_linkdown_clk = (nclk_val & NCLKCTRL_LINK_DOWN_SAVE); /* Save Non-Common Enabled Clocks */
KPRINT_INFO("%s : Port %d priv->pm_saved_linkdown_rst %x priv->pm_saved_linkdown_clk %x", __func__,
priv->port_num, priv->pm_saved_linkdown_rst, priv->pm_saved_linkdown_clk);
/* Assert Reset and Disable Clock */
nrst_val = nrst_val | NRSTCTRL_LINK_DOWN;
nclk_val = nclk_val & ~NCLKCTRL_LINK_DOWN;
KPRINT_INFO("%s : Port %d Wr RST Reg:%x, CLK Reg:%x", __func__, priv->port_num,
nrst_val, nclk_val);
writel(nrst_val, nrst_reg);
writel(nclk_val, nclk_reg);
if (tc956xmac_link_down_counter == TC956X_ALL_MAC_PORT_LINK_DOWN) {
/* Save Common register values */
commonrst_reg = priv->tc956x_SFR_pci_base_addr + NRSTCTRL0_OFFSET;
commonclk_reg = priv->tc956x_SFR_pci_base_addr + NCLKCTRL0_OFFSET;
commonrst_val = readl(commonrst_reg);
commonclk_val = readl(commonclk_reg);
KPRINT_INFO("%s : Port %d Common Rd RST Reg:%x, CLK Reg:%x", __func__, priv->port_num,
commonrst_val, commonclk_val);
pm_saved_cmn_linkdown_rst = ((~commonrst_val) & NRSTCTRL_LINK_DOWN_CMN_SAVE); /* Save Common De-Asserted Resets */
pm_saved_cmn_linkdown_clk = commonclk_val & NCLKCTRL_LINK_DOWN_CMN_SAVE; /* Save Common Enabled Clocks */
KPRINT_INFO("%s : Port %d pm_saved_cmn_linkdown_rst %x pm_saved_cmn_linkdown_clk %x", __func__,
priv->port_num, pm_saved_cmn_linkdown_rst, pm_saved_cmn_linkdown_clk);
}
} else if (state == LINK_UP) {
KPRINT_INFO("%s : Port %d Set Power for Link Up", __func__, priv->port_num);
if (tc956xmac_link_down_counter == TC956X_ALL_MAC_PORT_LINK_DOWN) {
/* Restore Common register values */
KPRINT_INFO("%s : Port %d pm_saved_cmn_linkdown_clk %x, pm_saved_cmn_linkdown_rst %x", __func__,
priv->port_num, pm_saved_cmn_linkdown_clk, pm_saved_cmn_linkdown_rst);
/* Enable Common Clock and De-Assert Common Resets */
commonclk_reg = priv->tc956x_SFR_pci_base_addr + NCLKCTRL0_OFFSET;
commonrst_reg = priv->tc956x_SFR_pci_base_addr + NRSTCTRL0_OFFSET;
commonclk_val = readl(commonclk_reg);
commonrst_val = readl(commonrst_reg);
KPRINT_INFO("%s : Port %d Common Rd CLK Reg:%x, RST Reg:%x ", __func__, priv->port_num,
commonclk_val, commonrst_val);
/* Clear Common Clocks only when both port suspends */
commonclk_val = (commonclk_val | pm_saved_cmn_linkdown_clk); /* Enable Common Saved Clock */
commonrst_val = (commonrst_val & (~pm_saved_cmn_linkdown_rst)); /* De-assert Common Saved Reset */
writel(commonclk_val, commonclk_reg);
writel(commonrst_val, commonrst_reg);
KPRINT_INFO("%s : Port %d Common Wr CLK Reg:%x, RST Reg:%x ", __func__, priv->port_num,
commonclk_val, commonrst_val);
KPRINT_INFO("%s : Port %d Common Rd CLK Reg:%x, RST Reg:%x", __func__, priv->port_num,
readl(commonclk_reg), readl(commonrst_reg));
}
/* Restore register values */
KPRINT_INFO("%s : Port %d pm_saved_linkdown_clk %x, pm_saved_linkdown_rst %x", __func__,
priv->port_num, priv->pm_saved_linkdown_clk, priv->pm_saved_linkdown_rst);
nclk_val = readl(nclk_reg);
nrst_val = readl(nrst_reg);
KPRINT_INFO("%s : Port %d Rd CLK Reg:%x, RST Reg:%x", __func__, priv->port_num,
nrst_val, nclk_val);
/* Restore values same as before link down */
nclk_val = (nclk_val | priv->pm_saved_linkdown_clk); /* Enable Saved Clock */
nrst_val = (nrst_val & (~(priv->pm_saved_linkdown_rst))); /* De-assert Saved Reset */
writel(nclk_val, nclk_reg);
writel(nrst_val, nrst_reg);
KPRINT_INFO("%s : Port %d Wr CLK Reg:%x, RST Reg:%x ", __func__, priv->port_num,
nclk_val, nrst_val);
tc956xmac_link_down_counter--; /* Decrement Counter Only when this api called */
priv->port_link_down = false;
}
KPRINT_INFO("%s : Port %d Rd RST Reg:%x, CLK Reg:%x", __func__, priv->port_num,
readl(nrst_reg), readl(nclk_reg));
KPRINT_INFO("<--%s : Port %d", __func__, priv->port_num);
}
#ifndef MODULE
static int __init tc956xmac_cmdline_opt(char *str)
{