@@ -191,7 +191,7 @@ struct ptp_ocp_i2c_info {
191
191
struct ptp_ocp_ext_info {
192
192
int index ;
193
193
irqreturn_t (* irq_fcn )(int irq , void * priv );
194
- int (* enable )(void * priv , bool enable );
194
+ int (* enable )(void * priv , u32 req , bool enable );
195
195
};
196
196
197
197
struct ptp_ocp_ext_src {
@@ -237,10 +237,14 @@ struct ptp_ocp {
237
237
int nmea_port ;
238
238
u8 serial [6 ];
239
239
bool has_serial ;
240
+ u32 pps_req_map ;
240
241
int flash_start ;
241
242
u32 utc_tai_offset ;
242
243
};
243
244
245
+ #define OCP_REQ_TIMESTAMP BIT(0)
246
+ #define OCP_REQ_PPS BIT(1)
247
+
244
248
struct ocp_resource {
245
249
unsigned long offset ;
246
250
int size ;
@@ -258,7 +262,7 @@ static int ptp_ocp_register_serial(struct ptp_ocp *bp, struct ocp_resource *r);
258
262
static int ptp_ocp_register_ext (struct ptp_ocp * bp , struct ocp_resource * r );
259
263
static int ptp_ocp_fb_board_init (struct ptp_ocp * bp , struct ocp_resource * r );
260
264
static irqreturn_t ptp_ocp_ts_irq (int irq , void * priv );
261
- static int ptp_ocp_ts_enable (void * priv , bool enable );
265
+ static int ptp_ocp_ts_enable (void * priv , u32 req , bool enable );
262
266
263
267
#define bp_assign_entry (bp , res , val ) ({ \
264
268
uintptr_t addr = (uintptr_t)(bp) + (res)->bp_offset; \
@@ -284,7 +288,7 @@ static int ptp_ocp_ts_enable(void *priv, bool enable);
284
288
OCP_RES_LOCATION(member), .setup = ptp_ocp_register_ext
285
289
286
290
/* This is the MSI vector mapping used.
287
- * 0: N/C
291
+ * 0: TS3 (and PPS)
288
292
* 1: TS0
289
293
* 2: TS1
290
294
* 3: GNSS
@@ -329,6 +333,15 @@ static struct ocp_resource ocp_fb_resource[] = {
329
333
.enable = ptp_ocp_ts_enable ,
330
334
},
331
335
},
336
+ {
337
+ OCP_EXT_RESOURCE (pps ),
338
+ .offset = 0x010C0000 , .size = 0x10000 , .irq_vec = 0 ,
339
+ .extra = & (struct ptp_ocp_ext_info ) {
340
+ .index = 3 ,
341
+ .irq_fcn = ptp_ocp_ts_irq ,
342
+ .enable = ptp_ocp_ts_enable ,
343
+ },
344
+ },
332
345
{
333
346
OCP_MEM_RESOURCE (pps_to_ext ),
334
347
.offset = 0x01030000 , .size = 0x10000 ,
@@ -634,10 +647,12 @@ ptp_ocp_enable(struct ptp_clock_info *ptp_info, struct ptp_clock_request *rq,
634
647
{
635
648
struct ptp_ocp * bp = container_of (ptp_info , struct ptp_ocp , ptp_info );
636
649
struct ptp_ocp_ext_src * ext = NULL ;
650
+ u32 req ;
637
651
int err ;
638
652
639
653
switch (rq -> type ) {
640
654
case PTP_CLK_REQ_EXTTS :
655
+ req = OCP_REQ_TIMESTAMP ;
641
656
switch (rq -> extts .index ) {
642
657
case 0 :
643
658
ext = bp -> ts0 ;
@@ -648,18 +663,30 @@ ptp_ocp_enable(struct ptp_clock_info *ptp_info, struct ptp_clock_request *rq,
648
663
case 2 :
649
664
ext = bp -> ts2 ;
650
665
break ;
666
+ case 3 :
667
+ ext = bp -> pps ;
668
+ break ;
651
669
}
652
670
break ;
653
671
case PTP_CLK_REQ_PPS :
672
+ req = OCP_REQ_PPS ;
654
673
ext = bp -> pps ;
655
674
break ;
675
+ case PTP_CLK_REQ_PEROUT :
676
+ if (on &&
677
+ (rq -> perout .period .sec != 1 || rq -> perout .period .nsec != 0 ))
678
+ return - EINVAL ;
679
+ /* This is a request for 1PPS on an output SMA.
680
+ * Allow, but assume manual configuration.
681
+ */
682
+ return 0 ;
656
683
default :
657
684
return - EOPNOTSUPP ;
658
685
}
659
686
660
687
err = - ENXIO ;
661
688
if (ext )
662
- err = ext -> info -> enable (ext , on );
689
+ err = ext -> info -> enable (ext , req , on );
663
690
664
691
return err ;
665
692
}
@@ -675,7 +702,8 @@ static const struct ptp_clock_info ptp_ocp_clock_info = {
675
702
.adjphase = ptp_ocp_adjphase ,
676
703
.enable = ptp_ocp_enable ,
677
704
.pps = true,
678
- .n_ext_ts = 3 ,
705
+ .n_ext_ts = 4 ,
706
+ .n_per_out = 1 ,
679
707
};
680
708
681
709
static void
@@ -1163,6 +1191,16 @@ ptp_ocp_ts_irq(int irq, void *priv)
1163
1191
struct ptp_clock_event ev ;
1164
1192
u32 sec , nsec ;
1165
1193
1194
+ if (ext == ext -> bp -> pps ) {
1195
+ if (ext -> bp -> pps_req_map & OCP_REQ_PPS ) {
1196
+ ev .type = PTP_CLOCK_PPS ;
1197
+ ptp_clock_event (ext -> bp -> ptp , & ev );
1198
+ }
1199
+
1200
+ if ((ext -> bp -> pps_req_map & ~OCP_REQ_PPS ) == 0 )
1201
+ goto out ;
1202
+ }
1203
+
1166
1204
/* XXX should fix API - this converts s/ns -> ts -> s/ns */
1167
1205
sec = ioread32 (& reg -> time_sec );
1168
1206
nsec = ioread32 (& reg -> time_ns );
@@ -1173,16 +1211,31 @@ ptp_ocp_ts_irq(int irq, void *priv)
1173
1211
1174
1212
ptp_clock_event (ext -> bp -> ptp , & ev );
1175
1213
1214
+ out :
1176
1215
iowrite32 (1 , & reg -> intr ); /* write 1 to ack */
1177
1216
1178
1217
return IRQ_HANDLED ;
1179
1218
}
1180
1219
1181
1220
static int
1182
- ptp_ocp_ts_enable (void * priv , bool enable )
1221
+ ptp_ocp_ts_enable (void * priv , u32 req , bool enable )
1183
1222
{
1184
1223
struct ptp_ocp_ext_src * ext = priv ;
1185
1224
struct ts_reg __iomem * reg = ext -> mem ;
1225
+ struct ptp_ocp * bp = ext -> bp ;
1226
+
1227
+ if (ext == bp -> pps ) {
1228
+ u32 old_map = bp -> pps_req_map ;
1229
+
1230
+ if (enable )
1231
+ bp -> pps_req_map |= req ;
1232
+ else
1233
+ bp -> pps_req_map &= ~req ;
1234
+
1235
+ /* if no state change, just return */
1236
+ if ((!!old_map ^ !!bp -> pps_req_map ) == 0 )
1237
+ return 0 ;
1238
+ }
1186
1239
1187
1240
if (enable ) {
1188
1241
iowrite32 (1 , & reg -> enable );
@@ -1199,7 +1252,7 @@ ptp_ocp_ts_enable(void *priv, bool enable)
1199
1252
static void
1200
1253
ptp_ocp_unregister_ext (struct ptp_ocp_ext_src * ext )
1201
1254
{
1202
- ext -> info -> enable (ext , false);
1255
+ ext -> info -> enable (ext , ~ 0 , false);
1203
1256
pci_free_irq (ext -> bp -> pdev , ext -> irq_vec , ext );
1204
1257
kfree (ext );
1205
1258
}
@@ -1889,8 +1942,8 @@ ptp_ocp_summary_show(struct seq_file *s, void *data)
1889
1942
struct timespec64 ts ;
1890
1943
struct ptp_ocp * bp ;
1891
1944
const char * src ;
1945
+ bool on , map ;
1892
1946
char * buf ;
1893
- bool on ;
1894
1947
1895
1948
buf = (char * )__get_free_page (GFP_KERNEL );
1896
1949
if (!buf )
@@ -1938,6 +1991,19 @@ ptp_ocp_summary_show(struct seq_file *s, void *data)
1938
1991
on ? " ON" : "OFF" , src );
1939
1992
}
1940
1993
1994
+ if (bp -> pps ) {
1995
+ ts_reg = bp -> pps -> mem ;
1996
+ src = "PHC" ;
1997
+ on = ioread32 (& ts_reg -> enable );
1998
+ map = !!(bp -> pps_req_map & OCP_REQ_TIMESTAMP );
1999
+ seq_printf (s , "%7s: %s, src: %s\n" , "TS3" ,
2000
+ on & map ? " ON" : "OFF" , src );
2001
+
2002
+ map = !!(bp -> pps_req_map & OCP_REQ_PPS );
2003
+ seq_printf (s , "%7s: %s, src: %s\n" , "PPS" ,
2004
+ on & map ? " ON" : "OFF" , src );
2005
+ }
2006
+
1941
2007
if (bp -> irig_out ) {
1942
2008
ctrl = ioread32 (& bp -> irig_out -> ctrl );
1943
2009
on = ctrl & IRIG_M_CTRL_ENABLE ;
0 commit comments