Commit 99bbc4ae authored by Yi Guo's avatar Yi Guo Committed by David S. Miller
Browse files

octeontx2-af: Add external ptp input clock



PTP hardware block can be configured to utilize
the external clock. Also the current ptp timestamp
can be captured when external trigger is applied on
a gpio pin. These features are required in scenarios
like connecting a external timing device to the chip
for time synchronization. The timing device provides
the clock and trigger(PPS signal) to the PTP block.
This patch does the following:
1. configures PTP block to use external clock
frequency and timestamp capture on external event.
2. sends PTP_REQ_EXTTS events to kernel ptp phc susbsytem
with captured timestamps
3. aligns PPS edge to adjusted ptp clock in the ptp device
by setting the PPS_THRESH to the reminder of the last
timestamp value captured by external PPS

Signed-off-by: default avatarYi Guo <yig@marvell.com>
Signed-off-by: default avatarHariprasad Kelam <hkelam@marvell.com>
Signed-off-by: default avatarSubbaraya Sundeep <sbhatta@marvell.com>
Signed-off-by: default avatarSunil Goutham <sgoutham@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e266f663
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1420,12 +1420,15 @@ struct npc_mcam_get_stats_rsp {
enum ptp_op {
	PTP_OP_ADJFINE = 0,
	PTP_OP_GET_CLOCK = 1,
	PTP_OP_GET_TSTMP = 2,
	PTP_OP_SET_THRESH = 3,
};

struct ptp_req {
	struct mbox_msghdr hdr;
	u8 op;
	s64 scaled_ppm;
	u64 thresh;
};

struct ptp_rsp {
+54 −1
Original line number Diff line number Diff line
@@ -30,9 +30,22 @@

#define PTP_CLOCK_CFG				0xF00ULL
#define PTP_CLOCK_CFG_PTP_EN			BIT_ULL(0)
#define PTP_CLOCK_CFG_EXT_CLK_EN		BIT_ULL(1)
#define PTP_CLOCK_CFG_EXT_CLK_IN_MASK		GENMASK_ULL(7, 2)
#define PTP_CLOCK_CFG_TSTMP_EDGE		BIT_ULL(9)
#define PTP_CLOCK_CFG_TSTMP_EN			BIT_ULL(8)
#define PTP_CLOCK_CFG_TSTMP_IN_MASK		GENMASK_ULL(15, 10)
#define PTP_CLOCK_CFG_PPS_EN			BIT_ULL(30)
#define PTP_CLOCK_CFG_PPS_INV			BIT_ULL(31)

#define PTP_PPS_HI_INCR				0xF60ULL
#define PTP_PPS_LO_INCR				0xF68ULL
#define PTP_PPS_THRESH_HI			0xF58ULL

#define PTP_CLOCK_LO				0xF08ULL
#define PTP_CLOCK_HI				0xF10ULL
#define PTP_CLOCK_COMP				0xF18ULL
#define PTP_TIMESTAMP				0xF20ULL

static struct ptp *first_ptp_block;
static const struct pci_device_id ptp_id_table[];
@@ -107,7 +120,7 @@ static int ptp_get_clock(struct ptp *ptp, u64 *clk)
	return 0;
}

void ptp_start(struct ptp *ptp, u64 sclk)
void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts)
{
	struct pci_dev *pdev;
	u64 clock_comp;
@@ -128,14 +141,48 @@ void ptp_start(struct ptp *ptp, u64 sclk)

	/* Enable PTP clock */
	clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);

	if (ext_clk_freq) {
		ptp->clock_rate = ext_clk_freq;
		/* Set GPIO as PTP clock source */
		clock_cfg &= ~PTP_CLOCK_CFG_EXT_CLK_IN_MASK;
		clock_cfg |= PTP_CLOCK_CFG_EXT_CLK_EN;
	}

	if (extts) {
		clock_cfg |= PTP_CLOCK_CFG_TSTMP_EDGE;
		/* Set GPIO as timestamping source */
		clock_cfg &= ~PTP_CLOCK_CFG_TSTMP_IN_MASK;
		clock_cfg |= PTP_CLOCK_CFG_TSTMP_EN;
	}

	clock_cfg |= PTP_CLOCK_CFG_PTP_EN;
	clock_cfg |= PTP_CLOCK_CFG_PPS_EN | PTP_CLOCK_CFG_PPS_INV;
	writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);

	/* Set 50% duty cycle for 1Hz output */
	writeq(0x1dcd650000000000, ptp->reg_base + PTP_PPS_HI_INCR);
	writeq(0x1dcd650000000000, ptp->reg_base + PTP_PPS_LO_INCR);

	clock_comp = ((u64)1000000000ull << 32) / ptp->clock_rate;
	/* Initial compensation value to start the nanosecs counter */
	writeq(clock_comp, ptp->reg_base + PTP_CLOCK_COMP);
}

static int ptp_get_tstmp(struct ptp *ptp, u64 *clk)
{
	*clk = readq(ptp->reg_base + PTP_TIMESTAMP);

	return 0;
}

static int ptp_set_thresh(struct ptp *ptp, u64 thresh)
{
	writeq(thresh, ptp->reg_base + PTP_PPS_THRESH_HI);

	return 0;
}

static int ptp_probe(struct pci_dev *pdev,
		     const struct pci_device_id *ent)
{
@@ -250,6 +297,12 @@ int rvu_mbox_handler_ptp_op(struct rvu *rvu, struct ptp_req *req,
	case PTP_OP_GET_CLOCK:
		err = ptp_get_clock(rvu->ptp, &rsp->clk);
		break;
	case PTP_OP_GET_TSTMP:
		err = ptp_get_tstmp(rvu->ptp, &rsp->clk);
		break;
	case PTP_OP_SET_THRESH:
		err = ptp_set_thresh(rvu->ptp, req->thresh);
		break;
	default:
		err = -EINVAL;
		break;
+1 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ struct ptp {

struct ptp *ptp_get(void);
void ptp_put(struct ptp *ptp);
void ptp_start(struct ptp *ptp, u64 sclk);
void ptp_start(struct ptp *ptp, u64 sclk, u32 ext_clk_freq, u32 extts);

extern struct pci_driver ptp_driver;

+2 −1
Original line number Diff line number Diff line
@@ -3241,7 +3241,8 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	mutex_init(&rvu->rswitch.switch_lock);

	if (rvu->fwdata)
		ptp_start(rvu->ptp, rvu->fwdata->sclk);
		ptp_start(rvu->ptp, rvu->fwdata->sclk, rvu->fwdata->ptp_ext_clk_rate,
			  rvu->fwdata->ptp_ext_tstamp);

	return 0;
err_dl:
+3 −1
Original line number Diff line number Diff line
@@ -396,7 +396,9 @@ struct rvu_fwdata {
	u64 mcam_addr;
	u64 mcam_sz;
	u64 msixtr_base;
#define FWDATA_RESERVED_MEM 1023
	u32 ptp_ext_clk_rate;
	u32 ptp_ext_tstamp;
#define FWDATA_RESERVED_MEM 1022
	u64 reserved[FWDATA_RESERVED_MEM];
#define CGX_MAX         5
#define CGX_LMACS_MAX   4
Loading