@@ -191,7 +191,7 @@ struct ptp_ocp_i2c_info {
191191struct ptp_ocp_ext_info {
192192 int index ;
193193 irqreturn_t (* irq_fcn )(int irq , void * priv );
194- int (* enable )(void * priv , bool enable );
194+ int (* enable )(void * priv , u32 req , bool enable );
195195};
196196
197197struct ptp_ocp_ext_src {
@@ -237,10 +237,14 @@ struct ptp_ocp {
237237 int nmea_port ;
238238 u8 serial [6 ];
239239 bool has_serial ;
240+ u32 pps_req_map ;
240241 int flash_start ;
241242 u32 utc_tai_offset ;
242243};
243244
245+ #define OCP_REQ_TIMESTAMP BIT(0)
246+ #define OCP_REQ_PPS BIT(1)
247+
244248struct ocp_resource {
245249 unsigned long offset ;
246250 int size ;
@@ -258,7 +262,7 @@ static int ptp_ocp_register_serial(struct ptp_ocp *bp, struct ocp_resource *r);
258262static int ptp_ocp_register_ext (struct ptp_ocp * bp , struct ocp_resource * r );
259263static int ptp_ocp_fb_board_init (struct ptp_ocp * bp , struct ocp_resource * r );
260264static 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 );
262266
263267#define bp_assign_entry (bp , res , val ) ({ \
264268 uintptr_t addr = (uintptr_t)(bp) + (res)->bp_offset; \
@@ -284,7 +288,7 @@ static int ptp_ocp_ts_enable(void *priv, bool enable);
284288 OCP_RES_LOCATION(member), .setup = ptp_ocp_register_ext
285289
286290/* This is the MSI vector mapping used.
287- * 0: N/C
291+ * 0: TS3 (and PPS)
288292 * 1: TS0
289293 * 2: TS1
290294 * 3: GNSS
@@ -329,6 +333,15 @@ static struct ocp_resource ocp_fb_resource[] = {
329333 .enable = ptp_ocp_ts_enable ,
330334 },
331335 },
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+ },
332345 {
333346 OCP_MEM_RESOURCE (pps_to_ext ),
334347 .offset = 0x01030000 , .size = 0x10000 ,
@@ -634,10 +647,12 @@ ptp_ocp_enable(struct ptp_clock_info *ptp_info, struct ptp_clock_request *rq,
634647{
635648 struct ptp_ocp * bp = container_of (ptp_info , struct ptp_ocp , ptp_info );
636649 struct ptp_ocp_ext_src * ext = NULL ;
650+ u32 req ;
637651 int err ;
638652
639653 switch (rq -> type ) {
640654 case PTP_CLK_REQ_EXTTS :
655+ req = OCP_REQ_TIMESTAMP ;
641656 switch (rq -> extts .index ) {
642657 case 0 :
643658 ext = bp -> ts0 ;
@@ -648,18 +663,30 @@ ptp_ocp_enable(struct ptp_clock_info *ptp_info, struct ptp_clock_request *rq,
648663 case 2 :
649664 ext = bp -> ts2 ;
650665 break ;
666+ case 3 :
667+ ext = bp -> pps ;
668+ break ;
651669 }
652670 break ;
653671 case PTP_CLK_REQ_PPS :
672+ req = OCP_REQ_PPS ;
654673 ext = bp -> pps ;
655674 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 ;
656683 default :
657684 return - EOPNOTSUPP ;
658685 }
659686
660687 err = - ENXIO ;
661688 if (ext )
662- err = ext -> info -> enable (ext , on );
689+ err = ext -> info -> enable (ext , req , on );
663690
664691 return err ;
665692}
@@ -675,7 +702,8 @@ static const struct ptp_clock_info ptp_ocp_clock_info = {
675702 .adjphase = ptp_ocp_adjphase ,
676703 .enable = ptp_ocp_enable ,
677704 .pps = true,
678- .n_ext_ts = 3 ,
705+ .n_ext_ts = 4 ,
706+ .n_per_out = 1 ,
679707};
680708
681709static void
@@ -1163,6 +1191,16 @@ ptp_ocp_ts_irq(int irq, void *priv)
11631191 struct ptp_clock_event ev ;
11641192 u32 sec , nsec ;
11651193
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+
11661204 /* XXX should fix API - this converts s/ns -> ts -> s/ns */
11671205 sec = ioread32 (& reg -> time_sec );
11681206 nsec = ioread32 (& reg -> time_ns );
@@ -1173,16 +1211,31 @@ ptp_ocp_ts_irq(int irq, void *priv)
11731211
11741212 ptp_clock_event (ext -> bp -> ptp , & ev );
11751213
1214+ out :
11761215 iowrite32 (1 , & reg -> intr ); /* write 1 to ack */
11771216
11781217 return IRQ_HANDLED ;
11791218}
11801219
11811220static int
1182- ptp_ocp_ts_enable (void * priv , bool enable )
1221+ ptp_ocp_ts_enable (void * priv , u32 req , bool enable )
11831222{
11841223 struct ptp_ocp_ext_src * ext = priv ;
11851224 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+ }
11861239
11871240 if (enable ) {
11881241 iowrite32 (1 , & reg -> enable );
@@ -1199,7 +1252,7 @@ ptp_ocp_ts_enable(void *priv, bool enable)
11991252static void
12001253ptp_ocp_unregister_ext (struct ptp_ocp_ext_src * ext )
12011254{
1202- ext -> info -> enable (ext , false);
1255+ ext -> info -> enable (ext , ~ 0 , false);
12031256 pci_free_irq (ext -> bp -> pdev , ext -> irq_vec , ext );
12041257 kfree (ext );
12051258}
@@ -1889,8 +1942,8 @@ ptp_ocp_summary_show(struct seq_file *s, void *data)
18891942 struct timespec64 ts ;
18901943 struct ptp_ocp * bp ;
18911944 const char * src ;
1945+ bool on , map ;
18921946 char * buf ;
1893- bool on ;
18941947
18951948 buf = (char * )__get_free_page (GFP_KERNEL );
18961949 if (!buf )
@@ -1938,6 +1991,19 @@ ptp_ocp_summary_show(struct seq_file *s, void *data)
19381991 on ? " ON" : "OFF" , src );
19391992 }
19401993
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+
19412007 if (bp -> irig_out ) {
19422008 ctrl = ioread32 (& bp -> irig_out -> ctrl );
19432009 on = ctrl & IRIG_M_CTRL_ENABLE ;
0 commit comments