Skip to content

Commit 395c92c

Browse files
Russell King (Oracle)kuba-moo
authored andcommitted
net: stmmac: add new MAC method set_lpi_mode()
Add a new method to control LPI mode configuration. This is architected to have three configuration states: LPI disabled, LPI forced (active), or LPI under hardware timer control. This reflects the three modes which the main body of the driver wishes to deal with. We pass in whether transmit clock gating should be used, and the hardware timer value in microseconds to be set when using hardware timer control. Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> Link: https://patch.msgid.link/E1tffds-003ZIT-E8@rmk-PC.armlinux.org.uk Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 6e37877 commit 395c92c

File tree

4 files changed

+102
-61
lines changed

4 files changed

+102
-61
lines changed

drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -342,31 +342,35 @@ static int dwmac1000_irq_status(struct mac_device_info *hw,
342342
return ret;
343343
}
344344

345-
static void dwmac1000_set_eee_mode(struct mac_device_info *hw,
346-
bool en_tx_lpi_clockgating)
345+
static int dwmac1000_set_lpi_mode(struct mac_device_info *hw,
346+
enum stmmac_lpi_mode mode,
347+
bool en_tx_lpi_clockgating, u32 et)
347348
{
348349
void __iomem *ioaddr = hw->pcsr;
349350
u32 value;
350351

351-
/*TODO - en_tx_lpi_clockgating treatment */
352+
if (mode == STMMAC_LPI_TIMER)
353+
return -EOPNOTSUPP;
352354

353-
/* Enable the link status receive on RGMII, SGMII ore SMII
354-
* receive path and instruct the transmit to enter in LPI
355-
* state.
356-
*/
357355
value = readl(ioaddr + LPI_CTRL_STATUS);
358-
value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
356+
if (mode == STMMAC_LPI_FORCED)
357+
value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
358+
else
359+
value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);
359360
writel(value, ioaddr + LPI_CTRL_STATUS);
361+
362+
return 0;
360363
}
361364

362-
static void dwmac1000_reset_eee_mode(struct mac_device_info *hw)
365+
static void dwmac1000_set_eee_mode(struct mac_device_info *hw,
366+
bool en_tx_lpi_clockgating)
363367
{
364-
void __iomem *ioaddr = hw->pcsr;
365-
u32 value;
368+
dwmac1000_set_lpi_mode(hw, STMMAC_LPI_FORCED, en_tx_lpi_clockgating, 0);
369+
}
366370

367-
value = readl(ioaddr + LPI_CTRL_STATUS);
368-
value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);
369-
writel(value, ioaddr + LPI_CTRL_STATUS);
371+
static void dwmac1000_reset_eee_mode(struct mac_device_info *hw)
372+
{
373+
dwmac1000_set_lpi_mode(hw, STMMAC_LPI_DISABLE, false, 0);
370374
}
371375

372376
static void dwmac1000_set_eee_pls(struct mac_device_info *hw, int link)
@@ -509,6 +513,7 @@ const struct stmmac_ops dwmac1000_ops = {
509513
.pmt = dwmac1000_pmt,
510514
.set_umac_addr = dwmac1000_set_umac_addr,
511515
.get_umac_addr = dwmac1000_get_umac_addr,
516+
.set_lpi_mode = dwmac1000_set_lpi_mode,
512517
.set_eee_mode = dwmac1000_set_eee_mode,
513518
.reset_eee_mode = dwmac1000_reset_eee_mode,
514519
.set_eee_timer = dwmac1000_set_eee_timer,

drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c

Lines changed: 48 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -376,35 +376,61 @@ static void dwmac4_get_umac_addr(struct mac_device_info *hw,
376376
GMAC_ADDR_LOW(reg_n));
377377
}
378378

379-
static void dwmac4_set_eee_mode(struct mac_device_info *hw,
380-
bool en_tx_lpi_clockgating)
379+
static int dwmac4_set_lpi_mode(struct mac_device_info *hw,
380+
enum stmmac_lpi_mode mode,
381+
bool en_tx_lpi_clockgating, u32 et)
381382
{
382383
void __iomem *ioaddr = hw->pcsr;
383-
u32 value;
384+
u32 value, mask;
385+
386+
if (mode == STMMAC_LPI_DISABLE) {
387+
value = 0;
388+
} else {
389+
value = LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
390+
391+
if (mode == STMMAC_LPI_TIMER) {
392+
/* Return ERANGE if the timer is larger than the
393+
* register field.
394+
*/
395+
if (et > STMMAC_ET_MAX)
396+
return -ERANGE;
397+
398+
/* Set the hardware LPI entry timer */
399+
writel(et, ioaddr + GMAC4_LPI_ENTRY_TIMER);
400+
401+
/* Interpret a zero LPI entry timer to mean
402+
* immediate entry into LPI mode.
403+
*/
404+
if (et)
405+
value |= LPI_CTRL_STATUS_LPIATE;
406+
}
407+
408+
if (en_tx_lpi_clockgating)
409+
value |= LPI_CTRL_STATUS_LPITCSE;
410+
}
411+
412+
mask = LPI_CTRL_STATUS_LPIATE | LPI_CTRL_STATUS_LPIEN |
413+
LPI_CTRL_STATUS_LPITXA;
414+
415+
value |= readl(ioaddr + GMAC4_LPI_CTRL_STATUS) & ~mask;
416+
writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS);
417+
418+
return 0;
419+
}
384420

421+
static void dwmac4_set_eee_mode(struct mac_device_info *hw,
422+
bool en_tx_lpi_clockgating)
423+
{
385424
/* Enable the link status receive on RGMII, SGMII ore SMII
386425
* receive path and instruct the transmit to enter in LPI
387426
* state.
388427
*/
389-
value = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);
390-
value &= ~LPI_CTRL_STATUS_LPIATE;
391-
value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
392-
393-
if (en_tx_lpi_clockgating)
394-
value |= LPI_CTRL_STATUS_LPITCSE;
395-
396-
writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS);
428+
dwmac4_set_lpi_mode(hw, STMMAC_LPI_FORCED, en_tx_lpi_clockgating, 0);
397429
}
398430

399431
static void dwmac4_reset_eee_mode(struct mac_device_info *hw)
400432
{
401-
void __iomem *ioaddr = hw->pcsr;
402-
u32 value;
403-
404-
value = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);
405-
value &= ~(LPI_CTRL_STATUS_LPIATE | LPI_CTRL_STATUS_LPIEN |
406-
LPI_CTRL_STATUS_LPITXA);
407-
writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS);
433+
dwmac4_set_lpi_mode(hw, STMMAC_LPI_DISABLE, false, 0);
408434
}
409435

410436
static void dwmac4_set_eee_pls(struct mac_device_info *hw, int link)
@@ -424,23 +450,7 @@ static void dwmac4_set_eee_pls(struct mac_device_info *hw, int link)
424450

425451
static void dwmac4_set_eee_lpi_entry_timer(struct mac_device_info *hw, u32 et)
426452
{
427-
void __iomem *ioaddr = hw->pcsr;
428-
u32 value = et & STMMAC_ET_MAX;
429-
int regval;
430-
431-
/* Program LPI entry timer value into register */
432-
writel(value, ioaddr + GMAC4_LPI_ENTRY_TIMER);
433-
434-
/* Enable/disable LPI entry timer */
435-
regval = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);
436-
regval |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
437-
438-
if (et)
439-
regval |= LPI_CTRL_STATUS_LPIATE;
440-
else
441-
regval &= ~LPI_CTRL_STATUS_LPIATE;
442-
443-
writel(regval, ioaddr + GMAC4_LPI_CTRL_STATUS);
453+
dwmac4_set_lpi_mode(hw, STMMAC_LPI_TIMER, false, et & STMMAC_ET_MAX);
444454
}
445455

446456
static void dwmac4_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
@@ -1203,6 +1213,7 @@ const struct stmmac_ops dwmac4_ops = {
12031213
.pmt = dwmac4_pmt,
12041214
.set_umac_addr = dwmac4_set_umac_addr,
12051215
.get_umac_addr = dwmac4_get_umac_addr,
1216+
.set_lpi_mode = dwmac4_set_lpi_mode,
12061217
.set_eee_mode = dwmac4_set_eee_mode,
12071218
.reset_eee_mode = dwmac4_reset_eee_mode,
12081219
.set_eee_lpi_entry_timer = dwmac4_set_eee_lpi_entry_timer,
@@ -1247,6 +1258,7 @@ const struct stmmac_ops dwmac410_ops = {
12471258
.pmt = dwmac4_pmt,
12481259
.set_umac_addr = dwmac4_set_umac_addr,
12491260
.get_umac_addr = dwmac4_get_umac_addr,
1261+
.set_lpi_mode = dwmac4_set_lpi_mode,
12501262
.set_eee_mode = dwmac4_set_eee_mode,
12511263
.reset_eee_mode = dwmac4_reset_eee_mode,
12521264
.set_eee_lpi_entry_timer = dwmac4_set_eee_lpi_entry_timer,
@@ -1293,6 +1305,7 @@ const struct stmmac_ops dwmac510_ops = {
12931305
.pmt = dwmac4_pmt,
12941306
.set_umac_addr = dwmac4_set_umac_addr,
12951307
.get_umac_addr = dwmac4_get_umac_addr,
1308+
.set_lpi_mode = dwmac4_set_lpi_mode,
12961309
.set_eee_mode = dwmac4_set_eee_mode,
12971310
.reset_eee_mode = dwmac4_reset_eee_mode,
12981311
.set_eee_lpi_entry_timer = dwmac4_set_eee_lpi_entry_timer,

drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -425,29 +425,39 @@ static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
425425
addr[5] = (hi_addr >> 8) & 0xff;
426426
}
427427

428-
static void dwxgmac2_set_eee_mode(struct mac_device_info *hw,
429-
bool en_tx_lpi_clockgating)
428+
static int dwxgmac2_set_lpi_mode(struct mac_device_info *hw,
429+
enum stmmac_lpi_mode mode,
430+
bool en_tx_lpi_clockgating, u32 et)
430431
{
431432
void __iomem *ioaddr = hw->pcsr;
432433
u32 value;
433434

435+
if (mode == STMMAC_LPI_TIMER)
436+
return -EOPNOTSUPP;
437+
434438
value = readl(ioaddr + XGMAC_LPI_CTRL);
439+
if (mode == STMMAC_LPI_FORCED) {
440+
value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
441+
if (en_tx_lpi_clockgating)
442+
value |= LPI_CTRL_STATUS_LPITCSE;
443+
} else {
444+
value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA |
445+
LPI_CTRL_STATUS_LPITCSE);
446+
}
447+
writel(value, ioaddr + XGMAC_LPI_CTRL);
435448

436-
value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
437-
if (en_tx_lpi_clockgating)
438-
value |= LPI_CTRL_STATUS_LPITCSE;
449+
return 0;
450+
}
439451

440-
writel(value, ioaddr + XGMAC_LPI_CTRL);
452+
static void dwxgmac2_set_eee_mode(struct mac_device_info *hw,
453+
bool en_tx_lpi_clockgating)
454+
{
455+
dwxgmac2_set_lpi_mode(hw, STMMAC_LPI_FORCED, en_tx_lpi_clockgating, 0);
441456
}
442457

443458
static void dwxgmac2_reset_eee_mode(struct mac_device_info *hw)
444459
{
445-
void __iomem *ioaddr = hw->pcsr;
446-
u32 value;
447-
448-
value = readl(ioaddr + XGMAC_LPI_CTRL);
449-
value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA | LPI_CTRL_STATUS_LPITCSE);
450-
writel(value, ioaddr + XGMAC_LPI_CTRL);
460+
dwxgmac2_set_lpi_mode(hw, STMMAC_LPI_DISABLE, false, 0);
451461
}
452462

453463
static void dwxgmac2_set_eee_pls(struct mac_device_info *hw, int link)
@@ -1525,6 +1535,7 @@ const struct stmmac_ops dwxgmac210_ops = {
15251535
.pmt = dwxgmac2_pmt,
15261536
.set_umac_addr = dwxgmac2_set_umac_addr,
15271537
.get_umac_addr = dwxgmac2_get_umac_addr,
1538+
.set_lpi_mode = dwxgmac2_set_lpi_mode,
15281539
.set_eee_mode = dwxgmac2_set_eee_mode,
15291540
.reset_eee_mode = dwxgmac2_reset_eee_mode,
15301541
.set_eee_timer = dwxgmac2_set_eee_timer,
@@ -1582,6 +1593,7 @@ const struct stmmac_ops dwxlgmac2_ops = {
15821593
.pmt = dwxgmac2_pmt,
15831594
.set_umac_addr = dwxgmac2_set_umac_addr,
15841595
.get_umac_addr = dwxgmac2_get_umac_addr,
1596+
.set_lpi_mode = dwxgmac2_set_lpi_mode,
15851597
.set_eee_mode = dwxgmac2_set_eee_mode,
15861598
.reset_eee_mode = dwxgmac2_reset_eee_mode,
15871599
.set_eee_timer = dwxgmac2_set_eee_timer,

drivers/net/ethernet/stmicro/stmmac/hwif.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,12 @@ struct stmmac_pps_cfg;
306306
struct stmmac_rss;
307307
struct stmmac_est;
308308

309+
enum stmmac_lpi_mode {
310+
STMMAC_LPI_DISABLE,
311+
STMMAC_LPI_FORCED,
312+
STMMAC_LPI_TIMER,
313+
};
314+
309315
/* Helpers to program the MAC core */
310316
struct stmmac_ops {
311317
/* MAC core initialization */
@@ -360,6 +366,9 @@ struct stmmac_ops {
360366
unsigned int reg_n);
361367
void (*get_umac_addr)(struct mac_device_info *hw, unsigned char *addr,
362368
unsigned int reg_n);
369+
int (*set_lpi_mode)(struct mac_device_info *hw,
370+
enum stmmac_lpi_mode mode,
371+
bool en_tx_lpi_clockgating, u32 et);
363372
void (*set_eee_mode)(struct mac_device_info *hw,
364373
bool en_tx_lpi_clockgating);
365374
void (*reset_eee_mode)(struct mac_device_info *hw);
@@ -467,6 +476,8 @@ struct stmmac_ops {
467476
stmmac_do_void_callback(__priv, mac, set_umac_addr, __args)
468477
#define stmmac_get_umac_addr(__priv, __args...) \
469478
stmmac_do_void_callback(__priv, mac, get_umac_addr, __args)
479+
#define stmmac_set_lpi_mode(__priv, __args...) \
480+
stmmac_do_callback(__priv, mac, set_lpi_mode, __args)
470481
#define stmmac_set_eee_mode(__priv, __args...) \
471482
stmmac_do_void_callback(__priv, mac, set_eee_mode, __args)
472483
#define stmmac_reset_eee_mode(__priv, __args...) \

0 commit comments

Comments
 (0)