Commit cef122d4 authored by Roger Quadros's avatar Roger Quadros Committed by David S. Miller

net: ethernet: ti: am65-cpsw/cpts: Add suspend/resume helpers

CPTS looses context on suspend (e.g. on AM62).
Provide suspend/resume hooks in CPTS driver. These will be
invoked by CPSW driver if CPTS was instantiated by CPSW.
Signed-off-by: default avatarRoger Quadros <rogerq@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4e0243e7
...@@ -176,6 +176,16 @@ struct am65_cpts { ...@@ -176,6 +176,16 @@ struct am65_cpts {
u32 genf_enable; u32 genf_enable;
u32 hw_ts_enable; u32 hw_ts_enable;
struct sk_buff_head txq; 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 { struct am65_cpts_skb_cb_data {
...@@ -1029,6 +1039,72 @@ struct am65_cpts *am65_cpts_create(struct device *dev, void __iomem *regs, ...@@ -1029,6 +1039,72 @@ struct am65_cpts *am65_cpts_create(struct device *dev, void __iomem *regs,
} }
EXPORT_SYMBOL_GPL(am65_cpts_create); 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) static int am65_cpts_probe(struct platform_device *pdev)
{ {
struct device_node *node = pdev->dev.of_node; struct device_node *node = pdev->dev.of_node;
......
...@@ -28,6 +28,8 @@ u64 am65_cpts_ns_gettime(struct am65_cpts *cpts); ...@@ -28,6 +28,8 @@ u64 am65_cpts_ns_gettime(struct am65_cpts *cpts);
int am65_cpts_estf_enable(struct am65_cpts *cpts, int idx, int am65_cpts_estf_enable(struct am65_cpts *cpts, int idx,
struct am65_cpts_estf_cfg *cfg); struct am65_cpts_estf_cfg *cfg);
void am65_cpts_estf_disable(struct am65_cpts *cpts, int idx); 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 #else
static inline struct am65_cpts *am65_cpts_create(struct device *dev, static inline struct am65_cpts *am65_cpts_create(struct device *dev,
void __iomem *regs, void __iomem *regs,
...@@ -69,6 +71,14 @@ static inline int am65_cpts_estf_enable(struct am65_cpts *cpts, int idx, ...@@ -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_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
#endif /* K3_CPTS_H_ */ #endif /* K3_CPTS_H_ */
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