Skip to content

Commit 979ede9

Browse files
committed
net: macb: rework suspend/resume
This commit is based on internal commit [1] and reworks it based on latest driver format and keeping in mind that the driver is not used only by Atmel/Microchip SAMA5 SoCs. [1] commit db48b97 Author: Boris Brezillon <boris.brezillon@free-electrons.com> Date: Tue Dec 6 14:07:37 2016 +0100 net: macb: Add support for sama5d2 suspend-to-mem Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
1 parent 6a06093 commit 979ede9

2 files changed

Lines changed: 201 additions & 29 deletions

File tree

drivers/net/ethernet/cadence/macb.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,13 +1077,45 @@ struct macb_ptp_info {
10771077
struct ifreq *ifr, int cmd);
10781078
};
10791079

1080+
struct macb_sama5d2_pm_data {
1081+
u32 etht;
1082+
u32 usrio;
1083+
};
1084+
1085+
struct macb_pm_ops {
1086+
int (*suspend)(struct macb *bp);
1087+
int (*resume)(struct macb *bp);
1088+
};
1089+
1090+
struct macb_pm {
1091+
bool (*can_wol)(void);
1092+
const struct macb_pm_ops *ops;
1093+
const u32 data_size;
1094+
};
1095+
1096+
#ifdef CONFIG_PM
1097+
#define MACB_CONFIG_PM(name, can_wol_fn, suspend_fn, resume_fn, data_sz) \
1098+
static const struct macb_pm_ops name##_ops = { \
1099+
.suspend = suspend_fn, \
1100+
.resume = resume_fn, \
1101+
}; \
1102+
static const struct macb_pm name = { \
1103+
.can_wol = can_wol_fn, \
1104+
.ops = &name##_ops, \
1105+
.data_size = data_sz, \
1106+
}
1107+
#else
1108+
#define MACB_CONFIG_PM(name, can_wol_fn, suspend_fn, resume_fn, data_sz)
1109+
#endif
1110+
10801111
struct macb_config {
10811112
u32 caps;
10821113
unsigned int dma_burst_length;
10831114
int (*clk_init)(struct platform_device *pdev, struct clk **pclk,
10841115
struct clk **hclk, struct clk **tx_clk,
10851116
struct clk **rx_clk);
10861117
int (*init)(struct platform_device *pdev);
1118+
const struct macb_pm *pm;
10871119
int jumbo_max_len;
10881120
};
10891121

@@ -1214,6 +1246,8 @@ struct macb {
12141246
int tx_bd_rd_prefetch;
12151247

12161248
const struct macb_config *config;
1249+
1250+
void *pm_data;
12171251
};
12181252

12191253
#ifdef CONFIG_MACB_USE_HWSTAMP

drivers/net/ethernet/cadence/macb_main.c

Lines changed: 167 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/netdevice.h>
2626
#include <linux/etherdevice.h>
2727
#include <linux/dma-mapping.h>
28+
#include <linux/platform_data/atmel.h>
2829
#include <linux/platform_data/macb.h>
2930
#include <linux/platform_device.h>
3031
#include <linux/phy.h>
@@ -2797,10 +2798,14 @@ static int macb_get_ts_info(struct net_device *netdev,
27972798

27982799
static void gem_enable_flow_filters(struct macb *bp, bool enable)
27992800
{
2801+
struct net_device *netdev = bp->dev;
28002802
struct ethtool_rx_fs_item *item;
28012803
u32 t2_scr;
28022804
int num_t2_scr;
28032805

2806+
if (!(netdev->features & NETIF_F_NTUPLE))
2807+
return;
2808+
28042809
num_t2_scr = GEM_BFEXT(T2SCR, gem_readl(bp, DCFG8));
28052810

28062811
list_for_each_entry(item, &bp->rx_fs_list.list, list) {
@@ -2960,8 +2965,7 @@ static int gem_add_flow_filter(struct net_device *netdev,
29602965
gem_prog_cmp_regs(bp, fs);
29612966
bp->rx_fs_list.count++;
29622967
/* enable filtering if NTUPLE on */
2963-
if (netdev->features & NETIF_F_NTUPLE)
2964-
gem_enable_flow_filters(bp, 1);
2968+
gem_enable_flow_filters(bp, 1);
29652969

29662970
spin_unlock_irqrestore(&bp->rx_fs_lock, flags);
29672971
return 0;
@@ -3149,46 +3153,86 @@ static int macb_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
31493153
}
31503154
}
31513155

3156+
static inline void macb_set_txcsum_feature(struct macb *bp,
3157+
netdev_features_t features)
3158+
{
3159+
u32 val;
3160+
3161+
if (!macb_is_gem(bp))
3162+
return;
3163+
3164+
val = gem_readl(bp, DMACFG);
3165+
if (features & NETIF_F_HW_CSUM)
3166+
val |= GEM_BIT(TXCOEN);
3167+
else
3168+
val &= ~GEM_BIT(TXCOEN);
3169+
3170+
gem_writel(bp, DMACFG, val);
3171+
}
3172+
3173+
static inline void macb_set_rxcsum_feature(struct macb *bp,
3174+
netdev_features_t features)
3175+
{
3176+
struct net_device *netdev = bp->dev;
3177+
u32 val;
3178+
3179+
if (!macb_is_gem(bp))
3180+
return;
3181+
3182+
val = gem_readl(bp, NCFGR);
3183+
if ((features & NETIF_F_RXCSUM) && !(netdev->flags & IFF_PROMISC))
3184+
val |= GEM_BIT(RXCOEN);
3185+
else
3186+
val &= ~GEM_BIT(RXCOEN);
3187+
3188+
gem_writel(bp, NCFGR, val);
3189+
}
3190+
3191+
static inline void macb_set_rxflow_feature(struct macb *bp,
3192+
netdev_features_t features)
3193+
{
3194+
if (!macb_is_gem(bp))
3195+
return;
3196+
3197+
gem_enable_flow_filters(bp, !!(features & NETIF_F_NTUPLE));
3198+
}
3199+
31523200
static int macb_set_features(struct net_device *netdev,
31533201
netdev_features_t features)
31543202
{
31553203
struct macb *bp = netdev_priv(netdev);
31563204
netdev_features_t changed = features ^ netdev->features;
31573205

31583206
/* TX checksum offload */
3159-
if ((changed & NETIF_F_HW_CSUM) && macb_is_gem(bp)) {
3160-
u32 dmacfg;
3161-
3162-
dmacfg = gem_readl(bp, DMACFG);
3163-
if (features & NETIF_F_HW_CSUM)
3164-
dmacfg |= GEM_BIT(TXCOEN);
3165-
else
3166-
dmacfg &= ~GEM_BIT(TXCOEN);
3167-
gem_writel(bp, DMACFG, dmacfg);
3168-
}
3207+
if (changed & NETIF_F_HW_CSUM)
3208+
macb_set_txcsum_feature(bp, features);
31693209

31703210
/* RX checksum offload */
3171-
if ((changed & NETIF_F_RXCSUM) && macb_is_gem(bp)) {
3172-
u32 netcfg;
3173-
3174-
netcfg = gem_readl(bp, NCFGR);
3175-
if (features & NETIF_F_RXCSUM &&
3176-
!(netdev->flags & IFF_PROMISC))
3177-
netcfg |= GEM_BIT(RXCOEN);
3178-
else
3179-
netcfg &= ~GEM_BIT(RXCOEN);
3180-
gem_writel(bp, NCFGR, netcfg);
3181-
}
3211+
if (changed & NETIF_F_RXCSUM)
3212+
macb_set_rxcsum_feature(bp, features);
31823213

31833214
/* RX Flow Filters */
3184-
if ((changed & NETIF_F_NTUPLE) && macb_is_gem(bp)) {
3185-
bool turn_on = features & NETIF_F_NTUPLE;
3215+
if (changed & NETIF_F_NTUPLE)
3216+
macb_set_rxflow_feature(bp, features);
31863217

3187-
gem_enable_flow_filters(bp, turn_on);
3188-
}
31893218
return 0;
31903219
}
31913220

3221+
static void macb_restore_features(struct macb *bp)
3222+
{
3223+
struct net_device *netdev = bp->dev;
3224+
netdev_features_t features = netdev->features;
3225+
3226+
/* TX checksum offload */
3227+
macb_set_txcsum_feature(bp, features);
3228+
3229+
/* RX checksum offload */
3230+
macb_set_rxcsum_feature(bp, features);
3231+
3232+
/* RX Flow Filters */
3233+
macb_set_rxflow_feature(bp, features);
3234+
}
3235+
31923236
static const struct net_device_ops macb_netdev_ops = {
31933237
.ndo_open = macb_open,
31943238
.ndo_stop = macb_close,
@@ -3830,6 +3874,71 @@ static int at91ether_init(struct platform_device *pdev)
38303874
return 0;
38313875
}
38323876

3877+
static bool __maybe_unused macb_sama5d2_can_wol(void)
3878+
{
3879+
#ifdef CONFIG_ARCH_AT91
3880+
return at91_suspend_entering_slow_clock();
3881+
#else
3882+
return true;
3883+
#endif
3884+
}
3885+
3886+
static bool __maybe_unused macb_sama5d2_backup(void)
3887+
{
3888+
#ifdef CONFIG_ARCH_AT91
3889+
return at91_suspend_entering_backup();
3890+
#else
3891+
return false;
3892+
#endif
3893+
}
3894+
3895+
static int __maybe_unused macb_sama5d2_suspend(struct macb *bp)
3896+
{
3897+
struct macb_sama5d2_pm_data *pm_data = bp->pm_data;
3898+
struct net_device *netdev = bp->dev;
3899+
3900+
if (!macb_sama5d2_backup())
3901+
return -EPERM;
3902+
3903+
if (netdev->hw_features & NETIF_F_NTUPLE)
3904+
pm_data->etht = gem_readl_n(bp, ETHT, SCRT2_ETHT);
3905+
3906+
if (!(bp->caps & MACB_CAPS_USRIO_DISABLED))
3907+
pm_data->usrio = macb_or_gem_readl(bp, USRIO);
3908+
3909+
if (netif_running(netdev))
3910+
macb_close(netdev);
3911+
3912+
return 0;
3913+
}
3914+
3915+
static int __maybe_unused macb_sama5d2_resume(struct macb *bp)
3916+
{
3917+
struct macb_sama5d2_pm_data *pm_data = bp->pm_data;
3918+
struct net_device *netdev = bp->dev;
3919+
3920+
if (!macb_sama5d2_backup())
3921+
return -EPERM;
3922+
3923+
if (netdev->hw_features & NETIF_F_NTUPLE)
3924+
gem_writel_n(bp, ETHT, SCRT2_ETHT, pm_data->etht);
3925+
3926+
if (!(bp->caps & MACB_CAPS_USRIO_DISABLED))
3927+
macb_or_gem_writel(bp, USRIO, pm_data->usrio);
3928+
3929+
if (netif_running(netdev))
3930+
macb_open(netdev);
3931+
3932+
macb_set_rx_mode(bp->dev);
3933+
macb_restore_features(bp);
3934+
3935+
return 0;
3936+
}
3937+
3938+
MACB_CONFIG_PM(macb_sama5d2_pm, macb_sama5d2_can_wol,
3939+
macb_sama5d2_suspend, macb_sama5d2_resume,
3940+
sizeof(struct macb_sama5d2_pm_data));
3941+
38333942
static const struct macb_config at91sam9260_config = {
38343943
.caps = MACB_CAPS_USRIO_HAS_CLKEN | MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII,
38353944
.clk_init = macb_clk_init,
@@ -3848,6 +3957,7 @@ static const struct macb_config sama5d2_config = {
38483957
.dma_burst_length = 16,
38493958
.clk_init = macb_clk_init,
38503959
.init = macb_init,
3960+
.pm = &macb_sama5d2_pm,
38513961
};
38523962

38533963
static const struct macb_config sama5d3_config = {
@@ -3989,6 +4099,18 @@ static int macb_probe(struct platform_device *pdev)
39894099
bp->tx_clk = tx_clk;
39904100
bp->rx_clk = rx_clk;
39914101

4102+
if (bp->config->pm && bp->config->pm->data_size > 0) {
4103+
bp->pm_data = devm_kzalloc(&pdev->dev,
4104+
bp->config->pm->data_size,
4105+
GFP_KERNEL);
4106+
if (!bp->pm_data) {
4107+
err = -ENOMEM;
4108+
goto err_out_free_netdev;
4109+
}
4110+
} else {
4111+
bp->pm_data = NULL;
4112+
}
4113+
39924114
bp->wol = 0;
39934115
if (of_get_property(np, "magic-packet", NULL))
39944116
bp->wol |= MACB_WOL_HAS_MAGIC_PACKET;
@@ -4140,15 +4262,23 @@ static int __maybe_unused macb_suspend(struct device *dev)
41404262
struct platform_device *pdev = to_platform_device(dev);
41414263
struct net_device *netdev = platform_get_drvdata(pdev);
41424264
struct macb *bp = netdev_priv(netdev);
4265+
bool can_wol = true;
41434266

41444267
netif_carrier_off(netdev);
41454268
netif_device_detach(netdev);
41464269

4147-
if (bp->wol & MACB_WOL_ENABLED) {
4270+
if (bp->config->pm && bp->config->pm->can_wol())
4271+
can_wol = bp->config->pm->can_wol();
4272+
4273+
if (can_wol && (bp->wol & MACB_WOL_ENABLED)) {
41484274
macb_writel(bp, IER, MACB_BIT(WOL));
41494275
macb_writel(bp, WOL, MACB_BIT(MAG));
41504276
enable_irq_wake(bp->queues[0].irq);
41514277
} else {
4278+
if (bp->config->pm && bp->config->pm->ops &&
4279+
bp->config->pm->ops->suspend)
4280+
bp->config->pm->ops->suspend(bp);
4281+
41524282
clk_disable_unprepare(bp->tx_clk);
41534283
clk_disable_unprepare(bp->hclk);
41544284
clk_disable_unprepare(bp->pclk);
@@ -4163,8 +4293,12 @@ static int __maybe_unused macb_resume(struct device *dev)
41634293
struct platform_device *pdev = to_platform_device(dev);
41644294
struct net_device *netdev = platform_get_drvdata(pdev);
41654295
struct macb *bp = netdev_priv(netdev);
4296+
bool can_wol = true;
41664297

4167-
if (bp->wol & MACB_WOL_ENABLED) {
4298+
if (bp->config->pm && bp->config->pm->can_wol)
4299+
can_wol = bp->config->pm->can_wol();
4300+
4301+
if (can_wol && (bp->wol & MACB_WOL_ENABLED)) {
41684302
macb_writel(bp, IDR, MACB_BIT(WOL));
41694303
macb_writel(bp, WOL, 0);
41704304
disable_irq_wake(bp->queues[0].irq);
@@ -4173,6 +4307,10 @@ static int __maybe_unused macb_resume(struct device *dev)
41734307
clk_prepare_enable(bp->hclk);
41744308
clk_prepare_enable(bp->tx_clk);
41754309
clk_prepare_enable(bp->rx_clk);
4310+
4311+
if (bp->config->pm && bp->config->pm->ops &&
4312+
bp->config->pm->ops->resume)
4313+
bp->config->pm->ops->resume(bp);
41764314
}
41774315

41784316
netif_device_attach(netdev);

0 commit comments

Comments
 (0)