Commit e2dbda0f authored by David S. Miller's avatar David S. Miller

Merge branch 'am65-cpsw-suspend-resume'

Roger Quadros says:

====================
net: ethernet: ti: am65-cpsw: Add suspend/resume support

This series enables PM_SLEEP(suspend/resume) support to
the am65-cpsw network driver.

Dual-emac and Switch mode are tested to work with suspend/resume
on AM62-SK platform.

It can be verified on the following branch
https://github.com/rogerq/linux/commits/for-v6.2/am62-cpsw-lpm-1.0
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4e0243e7 1af3cb37
This diff is collapsed.
......@@ -55,12 +55,16 @@ struct am65_cpsw_port {
bool rx_ts_enabled;
struct am65_cpsw_qos qos;
struct devlink_port devlink_port;
/* Only for suspend resume context */
u32 vid_context;
};
struct am65_cpsw_host {
struct am65_cpsw_common *common;
void __iomem *port_base;
void __iomem *stat_base;
/* Only for suspend resume context */
u32 vid_context;
};
struct am65_cpsw_tx_chn {
......@@ -145,6 +149,8 @@ struct am65_cpsw_common {
struct net_device *hw_bridge_dev;
struct notifier_block am65_cpsw_netdevice_nb;
unsigned char switch_id[MAX_PHYS_ITEM_ID_LEN];
/* only for suspend/resume context restore */
u32 *ale_context;
};
struct am65_cpsw_ndev_stats {
......
......@@ -176,6 +176,16 @@ struct am65_cpts {
u32 genf_enable;
u32 hw_ts_enable;
struct sk_buff_head txq;
/* context save/restore */
u64 sr_cpts_ns;
u64 sr_ktime_ns;
u32 sr_control;
u32 sr_int_enable;
u32 sr_rftclk_sel;
u32 sr_ts_ppm_hi;
u32 sr_ts_ppm_low;
struct am65_genf_regs sr_genf[AM65_CPTS_GENF_MAX_NUM];
struct am65_genf_regs sr_estf[AM65_CPTS_ESTF_MAX_NUM];
};
struct am65_cpts_skb_cb_data {
......@@ -1029,6 +1039,72 @@ struct am65_cpts *am65_cpts_create(struct device *dev, void __iomem *regs,
}
EXPORT_SYMBOL_GPL(am65_cpts_create);
void am65_cpts_suspend(struct am65_cpts *cpts)
{
/* save state and disable CPTS */
cpts->sr_control = am65_cpts_read32(cpts, control);
cpts->sr_int_enable = am65_cpts_read32(cpts, int_enable);
cpts->sr_rftclk_sel = am65_cpts_read32(cpts, rftclk_sel);
cpts->sr_ts_ppm_hi = am65_cpts_read32(cpts, ts_ppm_hi);
cpts->sr_ts_ppm_low = am65_cpts_read32(cpts, ts_ppm_low);
cpts->sr_cpts_ns = am65_cpts_gettime(cpts, NULL);
cpts->sr_ktime_ns = ktime_to_ns(ktime_get_real());
am65_cpts_disable(cpts);
clk_disable(cpts->refclk);
/* Save GENF state */
memcpy_fromio(&cpts->sr_genf, &cpts->reg->genf, sizeof(cpts->sr_genf));
/* Save ESTF state */
memcpy_fromio(&cpts->sr_estf, &cpts->reg->estf, sizeof(cpts->sr_estf));
}
EXPORT_SYMBOL_GPL(am65_cpts_suspend);
void am65_cpts_resume(struct am65_cpts *cpts)
{
int i;
s64 ktime_ns;
/* restore state and enable CPTS */
clk_enable(cpts->refclk);
am65_cpts_write32(cpts, cpts->sr_rftclk_sel, rftclk_sel);
am65_cpts_set_add_val(cpts);
am65_cpts_write32(cpts, cpts->sr_control, control);
am65_cpts_write32(cpts, cpts->sr_int_enable, int_enable);
/* Restore time to saved CPTS time + time in suspend/resume */
ktime_ns = ktime_to_ns(ktime_get_real());
ktime_ns -= cpts->sr_ktime_ns;
am65_cpts_settime(cpts, cpts->sr_cpts_ns + ktime_ns);
/* Restore compensation (PPM) */
am65_cpts_write32(cpts, cpts->sr_ts_ppm_hi, ts_ppm_hi);
am65_cpts_write32(cpts, cpts->sr_ts_ppm_low, ts_ppm_low);
/* Restore GENF state */
for (i = 0; i < AM65_CPTS_GENF_MAX_NUM; i++) {
am65_cpts_write32(cpts, 0, genf[i].length); /* TRM sequence */
am65_cpts_write32(cpts, cpts->sr_genf[i].comp_hi, genf[i].comp_hi);
am65_cpts_write32(cpts, cpts->sr_genf[i].comp_lo, genf[i].comp_lo);
am65_cpts_write32(cpts, cpts->sr_genf[i].length, genf[i].length);
am65_cpts_write32(cpts, cpts->sr_genf[i].control, genf[i].control);
am65_cpts_write32(cpts, cpts->sr_genf[i].ppm_hi, genf[i].ppm_hi);
am65_cpts_write32(cpts, cpts->sr_genf[i].ppm_low, genf[i].ppm_low);
}
/* Restore ESTTF state */
for (i = 0; i < AM65_CPTS_ESTF_MAX_NUM; i++) {
am65_cpts_write32(cpts, 0, estf[i].length); /* TRM sequence */
am65_cpts_write32(cpts, cpts->sr_estf[i].comp_hi, estf[i].comp_hi);
am65_cpts_write32(cpts, cpts->sr_estf[i].comp_lo, estf[i].comp_lo);
am65_cpts_write32(cpts, cpts->sr_estf[i].length, estf[i].length);
am65_cpts_write32(cpts, cpts->sr_estf[i].control, estf[i].control);
am65_cpts_write32(cpts, cpts->sr_estf[i].ppm_hi, estf[i].ppm_hi);
am65_cpts_write32(cpts, cpts->sr_estf[i].ppm_low, estf[i].ppm_low);
}
}
EXPORT_SYMBOL_GPL(am65_cpts_resume);
static int am65_cpts_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
......
......@@ -28,6 +28,8 @@ u64 am65_cpts_ns_gettime(struct am65_cpts *cpts);
int am65_cpts_estf_enable(struct am65_cpts *cpts, int idx,
struct am65_cpts_estf_cfg *cfg);
void am65_cpts_estf_disable(struct am65_cpts *cpts, int idx);
void am65_cpts_suspend(struct am65_cpts *cpts);
void am65_cpts_resume(struct am65_cpts *cpts);
#else
static inline struct am65_cpts *am65_cpts_create(struct device *dev,
void __iomem *regs,
......@@ -69,6 +71,14 @@ static inline int am65_cpts_estf_enable(struct am65_cpts *cpts, int idx,
static inline void am65_cpts_estf_disable(struct am65_cpts *cpts, int idx)
{
}
static inline void am65_cpts_suspend(struct am65_cpts *cpts)
{
}
static inline void am65_cpts_resume(struct am65_cpts *cpts)
{
}
#endif
#endif /* K3_CPTS_H_ */
......@@ -1452,6 +1452,16 @@ void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data)
}
}
void cpsw_ale_restore(struct cpsw_ale *ale, u32 *data)
{
int i;
for (i = 0; i < ale->params.ale_entries; i++) {
cpsw_ale_write(ale, i, data);
data += ALE_ENTRY_WORDS;
}
}
u32 cpsw_ale_get_num_entries(struct cpsw_ale *ale)
{
return ale ? ale->params.ale_entries : 0;
......
......@@ -127,6 +127,7 @@ int cpsw_ale_control_get(struct cpsw_ale *ale, int port, int control);
int cpsw_ale_control_set(struct cpsw_ale *ale, int port,
int control, int value);
void cpsw_ale_dump(struct cpsw_ale *ale, u32 *data);
void cpsw_ale_restore(struct cpsw_ale *ale, u32 *data);
u32 cpsw_ale_get_num_entries(struct cpsw_ale *ale);
static inline int cpsw_ale_get_vlan_p0_untag(struct cpsw_ale *ale, u16 vid)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment