[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20221104132310.31577-2-rogerq@kernel.org>
Date: Fri, 4 Nov 2022 15:23:06 +0200
From: Roger Quadros <rogerq@...nel.org>
To: davem@...emloft.net
Cc: edumazet@...gle.com, kuba@...nel.org, pabeni@...hat.com,
vigneshr@...com, vibhore@...com, srk@...com,
netdev@...r.kernel.org, linux-kernel@...r.kernel.org,
Roger Quadros <rogerq@...nel.org>
Subject: [PATCH 1/5] 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: Roger Quadros <rogerq@...nel.org>
---
drivers/net/ethernet/ti/am65-cpts.c | 76 +++++++++++++++++++++++++++++
drivers/net/ethernet/ti/am65-cpts.h | 10 ++++
2 files changed, 86 insertions(+)
diff --git a/drivers/net/ethernet/ti/am65-cpts.c b/drivers/net/ethernet/ti/am65-cpts.c
index e2f0fb286143..7f928c343426 100644
--- a/drivers/net/ethernet/ti/am65-cpts.c
+++ b/drivers/net/ethernet/ti/am65-cpts.c
@@ -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;
diff --git a/drivers/net/ethernet/ti/am65-cpts.h b/drivers/net/ethernet/ti/am65-cpts.h
index cf9fbc28fd03..bd08f4b2edd2 100644
--- a/drivers/net/ethernet/ti/am65-cpts.h
+++ b/drivers/net/ethernet/ti/am65-cpts.h
@@ -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_ */
--
2.17.1
Powered by blists - more mailing lists