Skip to content

Commit

Permalink
ptp: ocp: Program the signal generators via PTP_CLK_REQ_PEROUT
Browse files Browse the repository at this point in the history
The signal generators can be programmed either via the sysfs
file or through a PTP_CLK_REQ_PEROUT ioctl request.

Signed-off-by: Jonathan Lemon <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
jlemon authored and davem330 committed Mar 11, 2022
1 parent b325af3 commit 1aa66a3
Showing 1 changed file with 94 additions and 9 deletions.
103 changes: 94 additions & 9 deletions drivers/ptp/ptp_ocp.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,8 @@ static int ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r);
static irqreturn_t ptp_ocp_ts_irq(int irq, void *priv);
static irqreturn_t ptp_ocp_signal_irq(int irq, void *priv);
static int ptp_ocp_ts_enable(void *priv, u32 req, bool enable);
static int ptp_ocp_signal_from_perout(struct ptp_ocp *bp, int gen,
struct ptp_perout_request *req);
static int ptp_ocp_signal_enable(void *priv, u32 req, bool enable);
static int ptp_ocp_sma_store(struct ptp_ocp *bp, const char *buf, int sma_nr);

Expand Down Expand Up @@ -867,13 +869,27 @@ ptp_ocp_enable(struct ptp_clock_info *ptp_info, struct ptp_clock_request *rq,
ext = bp->pps;
break;
case PTP_CLK_REQ_PEROUT:
if (on &&
(rq->perout.period.sec != 1 || rq->perout.period.nsec != 0))
return -EINVAL;
/* This is a request for 1PPS on an output SMA.
* Allow, but assume manual configuration.
*/
return 0;
switch (rq->perout.index) {
case 0:
/* This is a request for 1PPS on an output SMA.
* Allow, but assume manual configuration.
*/
if (on && (rq->perout.period.sec != 1 ||
rq->perout.period.nsec != 0))
return -EINVAL;
return 0;
case 1:
case 2:
case 3:
case 4:
req = rq->perout.index - 1;
ext = bp->signal_out[req];
err = ptp_ocp_signal_from_perout(bp, req, &rq->perout);
if (err)
return err;
break;
}
break;
default:
return -EOPNOTSUPP;
}
Expand All @@ -885,6 +901,24 @@ ptp_ocp_enable(struct ptp_clock_info *ptp_info, struct ptp_clock_request *rq,
return err;
}

static int
ptp_ocp_verify(struct ptp_clock_info *ptp_info, unsigned pin,
enum ptp_pin_function func, unsigned chan)
{
struct ptp_ocp *bp = container_of(ptp_info, struct ptp_ocp, ptp_info);
char buf[16];

if (func != PTP_PF_PEROUT)
return -EOPNOTSUPP;

if (chan)
sprintf(buf, "OUT: GEN%d", chan);
else
sprintf(buf, "OUT: PHC");

return ptp_ocp_sma_store(bp, buf, pin + 1);
}

static const struct ptp_clock_info ptp_ocp_clock_info = {
.owner = THIS_MODULE,
.name = KBUILD_MODNAME,
Expand All @@ -895,9 +929,10 @@ static const struct ptp_clock_info ptp_ocp_clock_info = {
.adjfine = ptp_ocp_null_adjfine,
.adjphase = ptp_ocp_null_adjphase,
.enable = ptp_ocp_enable,
.verify = ptp_ocp_verify,
.pps = true,
.n_ext_ts = 4,
.n_per_out = 1,
.n_per_out = 5,
};

static void
Expand Down Expand Up @@ -1465,6 +1500,30 @@ ptp_ocp_signal_set(struct ptp_ocp *bp, int gen, struct ptp_ocp_signal *s)
return 0;
}

static int
ptp_ocp_signal_from_perout(struct ptp_ocp *bp, int gen,
struct ptp_perout_request *req)
{
struct ptp_ocp_signal s = { };

s.polarity = bp->signal[gen].polarity;
s.period = ktime_set(req->period.sec, req->period.nsec);
if (!s.period)
return 0;

if (req->flags & PTP_PEROUT_DUTY_CYCLE) {
s.pulse = ktime_set(req->on.sec, req->on.nsec);
s.duty = ktime_divns(s.pulse * 100, s.period);
}

if (req->flags & PTP_PEROUT_PHASE)
s.phase = ktime_set(req->phase.sec, req->phase.nsec);
else
s.start = ktime_set(req->start.sec, req->start.nsec);

return ptp_ocp_signal_set(bp, gen, &s);
}

static int
ptp_ocp_signal_enable(void *priv, u32 req, bool enable)
{
Expand Down Expand Up @@ -1740,11 +1799,32 @@ ptp_ocp_sma_init(struct ptp_ocp *bp)
}
}

static int
ptp_ocp_fb_set_pins(struct ptp_ocp *bp)
{
struct ptp_pin_desc *config;
int i;

config = kzalloc(sizeof(*config) * 4, GFP_KERNEL);
if (!config)
return -ENOMEM;

for (i = 0; i < 4; i++) {
sprintf(config[i].name, "sma%d", i + 1);
config[i].index = i;
}

bp->ptp_info.n_pins = 4;
bp->ptp_info.pin_config = config;

return 0;
}

/* FB specific board initializers; last "resource" registered. */
static int
ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
{
int ver;
int ver, err;

bp->flash_start = 1024 * 4096;
bp->eeprom_map = fb_eeprom_map;
Expand All @@ -1761,6 +1841,10 @@ ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
ptp_ocp_sma_init(bp);
ptp_ocp_signal_init(bp);

err = ptp_ocp_fb_set_pins(bp);
if (err)
return err;

return ptp_ocp_init_clock(bp);
}

Expand Down Expand Up @@ -3238,6 +3322,7 @@ ptp_ocp_detach(struct ptp_ocp *bp)
pci_free_irq_vectors(bp->pdev);
if (bp->ptp)
ptp_clock_unregister(bp->ptp);
kfree(bp->ptp_info.pin_config);
device_unregister(&bp->dev);
}

Expand Down

0 comments on commit 1aa66a3

Please sign in to comment.