Skip to content

Commit f15bb6d

Browse files
Sasha NeftinJeff Kirsher
authored andcommitted
e1000e: Add support for S0ix
Implement flow for S0ix support. Modern SoCs support S0ix low power states during idle periods, which are sub-states of ACPI S0 that increase power saving while supporting an instant-on experience for providing lower latency that ACPI S0. The S0ix states shut off parts of the SoC when they are not in use, while still maintaning optimal performance. This patch add support for S0ix started from an Ice Lake platform. Suggested-by: "Rafael J. Wysocki" <[email protected]> Signed-off-by: Vitaly Lifshits <[email protected]> Signed-off-by: Rajneesh Bhardwaj <[email protected]> Signed-off-by: Sasha Neftin <[email protected]> Tested-by: Aaron Brown <[email protected]> Signed-off-by: Jeff Kirsher <[email protected]>
1 parent 0ac960a commit f15bb6d

File tree

2 files changed

+186
-0
lines changed

2 files changed

+186
-0
lines changed

drivers/net/ethernet/intel/e1000e/netdev.c

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6294,6 +6294,174 @@ static void e1000e_flush_lpic(struct pci_dev *pdev)
62946294
pm_runtime_put_sync(netdev->dev.parent);
62956295
}
62966296

6297+
/* S0ix implementation */
6298+
static void e1000e_s0ix_entry_flow(struct e1000_adapter *adapter)
6299+
{
6300+
struct e1000_hw *hw = &adapter->hw;
6301+
u32 mac_data;
6302+
u16 phy_data;
6303+
6304+
/* Disable the periodic inband message,
6305+
* don't request PCIe clock in K1 page770_17[10:9] = 10b
6306+
*/
6307+
e1e_rphy(hw, HV_PM_CTRL, &phy_data);
6308+
phy_data &= ~HV_PM_CTRL_K1_CLK_REQ;
6309+
phy_data |= BIT(10);
6310+
e1e_wphy(hw, HV_PM_CTRL, phy_data);
6311+
6312+
/* Make sure we don't exit K1 every time a new packet arrives
6313+
* 772_29[5] = 1 CS_Mode_Stay_In_K1
6314+
*/
6315+
e1e_rphy(hw, I217_CGFREG, &phy_data);
6316+
phy_data |= BIT(5);
6317+
e1e_wphy(hw, I217_CGFREG, phy_data);
6318+
6319+
/* Change the MAC/PHY interface to SMBus
6320+
* Force the SMBus in PHY page769_23[0] = 1
6321+
* Force the SMBus in MAC CTRL_EXT[11] = 1
6322+
*/
6323+
e1e_rphy(hw, CV_SMB_CTRL, &phy_data);
6324+
phy_data |= CV_SMB_CTRL_FORCE_SMBUS;
6325+
e1e_wphy(hw, CV_SMB_CTRL, phy_data);
6326+
mac_data = er32(CTRL_EXT);
6327+
mac_data |= E1000_CTRL_EXT_FORCE_SMBUS;
6328+
ew32(CTRL_EXT, mac_data);
6329+
6330+
/* DFT control: PHY bit: page769_20[0] = 1
6331+
* Gate PPW via EXTCNF_CTRL - set 0x0F00[7] = 1
6332+
*/
6333+
e1e_rphy(hw, I82579_DFT_CTRL, &phy_data);
6334+
phy_data |= BIT(0);
6335+
e1e_wphy(hw, I82579_DFT_CTRL, phy_data);
6336+
6337+
mac_data = er32(EXTCNF_CTRL);
6338+
mac_data |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
6339+
ew32(EXTCNF_CTRL, mac_data);
6340+
6341+
/* Check MAC Tx/Rx packet buffer pointers.
6342+
* Reset MAC Tx/Rx packet buffer pointers to suppress any
6343+
* pending traffic indication that would prevent power gating.
6344+
*/
6345+
mac_data = er32(TDFH);
6346+
if (mac_data)
6347+
ew32(TDFH, 0);
6348+
mac_data = er32(TDFT);
6349+
if (mac_data)
6350+
ew32(TDFT, 0);
6351+
mac_data = er32(TDFHS);
6352+
if (mac_data)
6353+
ew32(TDFHS, 0);
6354+
mac_data = er32(TDFTS);
6355+
if (mac_data)
6356+
ew32(TDFTS, 0);
6357+
mac_data = er32(TDFPC);
6358+
if (mac_data)
6359+
ew32(TDFPC, 0);
6360+
mac_data = er32(RDFH);
6361+
if (mac_data)
6362+
ew32(RDFH, 0);
6363+
mac_data = er32(RDFT);
6364+
if (mac_data)
6365+
ew32(RDFT, 0);
6366+
mac_data = er32(RDFHS);
6367+
if (mac_data)
6368+
ew32(RDFHS, 0);
6369+
mac_data = er32(RDFTS);
6370+
if (mac_data)
6371+
ew32(RDFTS, 0);
6372+
mac_data = er32(RDFPC);
6373+
if (mac_data)
6374+
ew32(RDFPC, 0);
6375+
6376+
/* Enable the Dynamic Power Gating in the MAC */
6377+
mac_data = er32(FEXTNVM7);
6378+
mac_data |= BIT(22);
6379+
ew32(FEXTNVM7, mac_data);
6380+
6381+
/* Disable the time synchronization clock */
6382+
mac_data = er32(FEXTNVM7);
6383+
mac_data |= BIT(31);
6384+
mac_data &= ~BIT(0);
6385+
ew32(FEXTNVM7, mac_data);
6386+
6387+
/* Dynamic Power Gating Enable */
6388+
mac_data = er32(CTRL_EXT);
6389+
mac_data |= BIT(3);
6390+
ew32(CTRL_EXT, mac_data);
6391+
6392+
/* Enable the Dynamic Clock Gating in the DMA and MAC */
6393+
mac_data = er32(CTRL_EXT);
6394+
mac_data |= E1000_CTRL_EXT_DMA_DYN_CLK_EN;
6395+
ew32(CTRL_EXT, mac_data);
6396+
6397+
/* No MAC DPG gating SLP_S0 in modern standby
6398+
* Switch the logic of the lanphypc to use PMC counter
6399+
*/
6400+
mac_data = er32(FEXTNVM5);
6401+
mac_data |= BIT(7);
6402+
ew32(FEXTNVM5, mac_data);
6403+
}
6404+
6405+
static void e1000e_s0ix_exit_flow(struct e1000_adapter *adapter)
6406+
{
6407+
struct e1000_hw *hw = &adapter->hw;
6408+
u32 mac_data;
6409+
u16 phy_data;
6410+
6411+
/* Disable the Dynamic Power Gating in the MAC */
6412+
mac_data = er32(FEXTNVM7);
6413+
mac_data &= 0xFFBFFFFF;
6414+
ew32(FEXTNVM7, mac_data);
6415+
6416+
/* Enable the time synchronization clock */
6417+
mac_data = er32(FEXTNVM7);
6418+
mac_data |= BIT(0);
6419+
ew32(FEXTNVM7, mac_data);
6420+
6421+
/* Disable Dynamic Power Gating */
6422+
mac_data = er32(CTRL_EXT);
6423+
mac_data &= 0xFFFFFFF7;
6424+
ew32(CTRL_EXT, mac_data);
6425+
6426+
/* Disable the Dynamic Clock Gating in the DMA and MAC */
6427+
mac_data = er32(CTRL_EXT);
6428+
mac_data &= 0xFFF7FFFF;
6429+
ew32(CTRL_EXT, mac_data);
6430+
6431+
/* Revert the lanphypc logic to use the internal Gbe counter
6432+
* and not the PMC counter
6433+
*/
6434+
mac_data = er32(FEXTNVM5);
6435+
mac_data &= 0xFFFFFF7F;
6436+
ew32(FEXTNVM5, mac_data);
6437+
6438+
/* Enable the periodic inband message,
6439+
* Request PCIe clock in K1 page770_17[10:9] =01b
6440+
*/
6441+
e1e_rphy(hw, HV_PM_CTRL, &phy_data);
6442+
phy_data &= 0xFBFF;
6443+
phy_data |= HV_PM_CTRL_K1_CLK_REQ;
6444+
e1e_wphy(hw, HV_PM_CTRL, phy_data);
6445+
6446+
/* Return back configuration
6447+
* 772_29[5] = 0 CS_Mode_Stay_In_K1
6448+
*/
6449+
e1e_rphy(hw, I217_CGFREG, &phy_data);
6450+
phy_data &= 0xFFDF;
6451+
e1e_wphy(hw, I217_CGFREG, phy_data);
6452+
6453+
/* Change the MAC/PHY interface to Kumeran
6454+
* Unforce the SMBus in PHY page769_23[0] = 0
6455+
* Unforce the SMBus in MAC CTRL_EXT[11] = 0
6456+
*/
6457+
e1e_rphy(hw, CV_SMB_CTRL, &phy_data);
6458+
phy_data &= ~CV_SMB_CTRL_FORCE_SMBUS;
6459+
e1e_wphy(hw, CV_SMB_CTRL, phy_data);
6460+
mac_data = er32(CTRL_EXT);
6461+
mac_data &= ~E1000_CTRL_EXT_FORCE_SMBUS;
6462+
ew32(CTRL_EXT, mac_data);
6463+
}
6464+
62976465
static int e1000e_pm_freeze(struct device *dev)
62986466
{
62996467
struct net_device *netdev = dev_get_drvdata(dev);
@@ -6649,7 +6817,10 @@ static int e1000e_pm_thaw(struct device *dev)
66496817

66506818
static int e1000e_pm_suspend(struct device *dev)
66516819
{
6820+
struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
6821+
struct e1000_adapter *adapter = netdev_priv(netdev);
66526822
struct pci_dev *pdev = to_pci_dev(dev);
6823+
struct e1000_hw *hw = &adapter->hw;
66536824
int rc;
66546825

66556826
e1000e_flush_lpic(pdev);
@@ -6660,14 +6831,25 @@ static int e1000e_pm_suspend(struct device *dev)
66606831
if (rc)
66616832
e1000e_pm_thaw(dev);
66626833

6834+
/* Introduce S0ix implementation */
6835+
if (hw->mac.type >= e1000_pch_cnp)
6836+
e1000e_s0ix_entry_flow(adapter);
6837+
66636838
return rc;
66646839
}
66656840

66666841
static int e1000e_pm_resume(struct device *dev)
66676842
{
6843+
struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev));
6844+
struct e1000_adapter *adapter = netdev_priv(netdev);
66686845
struct pci_dev *pdev = to_pci_dev(dev);
6846+
struct e1000_hw *hw = &adapter->hw;
66696847
int rc;
66706848

6849+
/* Introduce S0ix implementation */
6850+
if (hw->mac.type >= e1000_pch_cnp)
6851+
e1000e_s0ix_exit_flow(adapter);
6852+
66716853
rc = __e1000_resume(pdev);
66726854
if (rc)
66736855
return rc;

drivers/net/ethernet/intel/e1000e/regs.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */
1919
#define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */
2020
#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */
21+
#define E1000_FEXTNVM5 0x00014 /* Future Extended NVM 5 - RW */
2122
#define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */
2223
#define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */
2324
#define E1000_FEXTNVM9 0x5BB4 /* Future Extended NVM 9 - RW */
@@ -234,4 +235,7 @@
234235
#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */
235236
#define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */
236237

238+
/* PHY registers */
239+
#define I82579_DFT_CTRL PHY_REG(769, 20)
240+
237241
#endif

0 commit comments

Comments
 (0)