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

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
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
@@ -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;
+10 −0
Original line number Diff line number Diff line
@@ -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_ */