Skip to content

Commit 1aa66a3

Browse files
jlemondavem330
authored andcommitted
ptp: ocp: Program the signal generators via PTP_CLK_REQ_PEROUT
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]>
1 parent b325af3 commit 1aa66a3

File tree

1 file changed

+94
-9
lines changed

1 file changed

+94
-9
lines changed

drivers/ptp/ptp_ocp.c

Lines changed: 94 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,8 @@ static int ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r);
332332
static irqreturn_t ptp_ocp_ts_irq(int irq, void *priv);
333333
static irqreturn_t ptp_ocp_signal_irq(int irq, void *priv);
334334
static int ptp_ocp_ts_enable(void *priv, u32 req, bool enable);
335+
static int ptp_ocp_signal_from_perout(struct ptp_ocp *bp, int gen,
336+
struct ptp_perout_request *req);
335337
static int ptp_ocp_signal_enable(void *priv, u32 req, bool enable);
336338
static int ptp_ocp_sma_store(struct ptp_ocp *bp, const char *buf, int sma_nr);
337339

@@ -867,13 +869,27 @@ ptp_ocp_enable(struct ptp_clock_info *ptp_info, struct ptp_clock_request *rq,
867869
ext = bp->pps;
868870
break;
869871
case PTP_CLK_REQ_PEROUT:
870-
if (on &&
871-
(rq->perout.period.sec != 1 || rq->perout.period.nsec != 0))
872-
return -EINVAL;
873-
/* This is a request for 1PPS on an output SMA.
874-
* Allow, but assume manual configuration.
875-
*/
876-
return 0;
872+
switch (rq->perout.index) {
873+
case 0:
874+
/* This is a request for 1PPS on an output SMA.
875+
* Allow, but assume manual configuration.
876+
*/
877+
if (on && (rq->perout.period.sec != 1 ||
878+
rq->perout.period.nsec != 0))
879+
return -EINVAL;
880+
return 0;
881+
case 1:
882+
case 2:
883+
case 3:
884+
case 4:
885+
req = rq->perout.index - 1;
886+
ext = bp->signal_out[req];
887+
err = ptp_ocp_signal_from_perout(bp, req, &rq->perout);
888+
if (err)
889+
return err;
890+
break;
891+
}
892+
break;
877893
default:
878894
return -EOPNOTSUPP;
879895
}
@@ -885,6 +901,24 @@ ptp_ocp_enable(struct ptp_clock_info *ptp_info, struct ptp_clock_request *rq,
885901
return err;
886902
}
887903

904+
static int
905+
ptp_ocp_verify(struct ptp_clock_info *ptp_info, unsigned pin,
906+
enum ptp_pin_function func, unsigned chan)
907+
{
908+
struct ptp_ocp *bp = container_of(ptp_info, struct ptp_ocp, ptp_info);
909+
char buf[16];
910+
911+
if (func != PTP_PF_PEROUT)
912+
return -EOPNOTSUPP;
913+
914+
if (chan)
915+
sprintf(buf, "OUT: GEN%d", chan);
916+
else
917+
sprintf(buf, "OUT: PHC");
918+
919+
return ptp_ocp_sma_store(bp, buf, pin + 1);
920+
}
921+
888922
static const struct ptp_clock_info ptp_ocp_clock_info = {
889923
.owner = THIS_MODULE,
890924
.name = KBUILD_MODNAME,
@@ -895,9 +929,10 @@ static const struct ptp_clock_info ptp_ocp_clock_info = {
895929
.adjfine = ptp_ocp_null_adjfine,
896930
.adjphase = ptp_ocp_null_adjphase,
897931
.enable = ptp_ocp_enable,
932+
.verify = ptp_ocp_verify,
898933
.pps = true,
899934
.n_ext_ts = 4,
900-
.n_per_out = 1,
935+
.n_per_out = 5,
901936
};
902937

903938
static void
@@ -1465,6 +1500,30 @@ ptp_ocp_signal_set(struct ptp_ocp *bp, int gen, struct ptp_ocp_signal *s)
14651500
return 0;
14661501
}
14671502

1503+
static int
1504+
ptp_ocp_signal_from_perout(struct ptp_ocp *bp, int gen,
1505+
struct ptp_perout_request *req)
1506+
{
1507+
struct ptp_ocp_signal s = { };
1508+
1509+
s.polarity = bp->signal[gen].polarity;
1510+
s.period = ktime_set(req->period.sec, req->period.nsec);
1511+
if (!s.period)
1512+
return 0;
1513+
1514+
if (req->flags & PTP_PEROUT_DUTY_CYCLE) {
1515+
s.pulse = ktime_set(req->on.sec, req->on.nsec);
1516+
s.duty = ktime_divns(s.pulse * 100, s.period);
1517+
}
1518+
1519+
if (req->flags & PTP_PEROUT_PHASE)
1520+
s.phase = ktime_set(req->phase.sec, req->phase.nsec);
1521+
else
1522+
s.start = ktime_set(req->start.sec, req->start.nsec);
1523+
1524+
return ptp_ocp_signal_set(bp, gen, &s);
1525+
}
1526+
14681527
static int
14691528
ptp_ocp_signal_enable(void *priv, u32 req, bool enable)
14701529
{
@@ -1740,11 +1799,32 @@ ptp_ocp_sma_init(struct ptp_ocp *bp)
17401799
}
17411800
}
17421801

1802+
static int
1803+
ptp_ocp_fb_set_pins(struct ptp_ocp *bp)
1804+
{
1805+
struct ptp_pin_desc *config;
1806+
int i;
1807+
1808+
config = kzalloc(sizeof(*config) * 4, GFP_KERNEL);
1809+
if (!config)
1810+
return -ENOMEM;
1811+
1812+
for (i = 0; i < 4; i++) {
1813+
sprintf(config[i].name, "sma%d", i + 1);
1814+
config[i].index = i;
1815+
}
1816+
1817+
bp->ptp_info.n_pins = 4;
1818+
bp->ptp_info.pin_config = config;
1819+
1820+
return 0;
1821+
}
1822+
17431823
/* FB specific board initializers; last "resource" registered. */
17441824
static int
17451825
ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
17461826
{
1747-
int ver;
1827+
int ver, err;
17481828

17491829
bp->flash_start = 1024 * 4096;
17501830
bp->eeprom_map = fb_eeprom_map;
@@ -1761,6 +1841,10 @@ ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
17611841
ptp_ocp_sma_init(bp);
17621842
ptp_ocp_signal_init(bp);
17631843

1844+
err = ptp_ocp_fb_set_pins(bp);
1845+
if (err)
1846+
return err;
1847+
17641848
return ptp_ocp_init_clock(bp);
17651849
}
17661850

@@ -3238,6 +3322,7 @@ ptp_ocp_detach(struct ptp_ocp *bp)
32383322
pci_free_irq_vectors(bp->pdev);
32393323
if (bp->ptp)
32403324
ptp_clock_unregister(bp->ptp);
3325+
kfree(bp->ptp_info.pin_config);
32413326
device_unregister(&bp->dev);
32423327
}
32433328

0 commit comments

Comments
 (0)