31
31
ptp_clock_info)
32
32
#define dw_overflow_to_chip (dw ) container_of(dw, struct mv88e6xxx_chip, \
33
33
overflow_work)
34
+ #define dw_tai_event_to_chip (dw ) container_of(dw, struct mv88e6xxx_chip, \
35
+ tai_event_work)
34
36
35
37
static int mv88e6xxx_tai_read (struct mv88e6xxx_chip * chip , int addr ,
36
38
u16 * data , int len )
@@ -41,6 +43,30 @@ static int mv88e6xxx_tai_read(struct mv88e6xxx_chip *chip, int addr,
41
43
return chip -> info -> ops -> avb_ops -> tai_read (chip , addr , data , len );
42
44
}
43
45
46
+ static int mv88e6xxx_tai_write (struct mv88e6xxx_chip * chip , int addr , u16 data )
47
+ {
48
+ if (!chip -> info -> ops -> avb_ops -> tai_write )
49
+ return - EOPNOTSUPP ;
50
+
51
+ return chip -> info -> ops -> avb_ops -> tai_write (chip , addr , data );
52
+ }
53
+
54
+ /* TODO: places where this are called should be using pinctrl */
55
+ static int mv88e6xxx_set_gpio_func (struct mv88e6xxx_chip * chip , int pin ,
56
+ int func , int input )
57
+ {
58
+ int err ;
59
+
60
+ if (!chip -> info -> ops -> gpio_ops )
61
+ return - EOPNOTSUPP ;
62
+
63
+ err = chip -> info -> ops -> gpio_ops -> set_dir (chip , pin , input );
64
+ if (err )
65
+ return err ;
66
+
67
+ return chip -> info -> ops -> gpio_ops -> set_pctl (chip , pin , func );
68
+ }
69
+
44
70
static u64 mv88e6xxx_ptp_clock_read (const struct cyclecounter * cc )
45
71
{
46
72
struct mv88e6xxx_chip * chip = cc_to_chip (cc );
@@ -55,6 +81,92 @@ static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
55
81
return ((u32 )phc_time [1 ] << 16 ) | phc_time [0 ];
56
82
}
57
83
84
+ /* mv88e6xxx_config_eventcap - configure TAI event capture
85
+ * @event: PTP_CLOCK_PPS (internal) or PTP_CLOCK_EXTTS (external)
86
+ * @rising: zero for falling-edge trigger, else rising-edge trigger
87
+ *
88
+ * This will also reset the capture sequence counter.
89
+ */
90
+ static int mv88e6xxx_config_eventcap (struct mv88e6xxx_chip * chip , int event ,
91
+ int rising )
92
+ {
93
+ u16 global_config ;
94
+ u16 cap_config ;
95
+ int err ;
96
+
97
+ chip -> evcap_config = MV88E6XXX_TAI_CFG_CAP_OVERWRITE |
98
+ MV88E6XXX_TAI_CFG_CAP_CTR_START ;
99
+ if (!rising )
100
+ chip -> evcap_config |= MV88E6XXX_TAI_CFG_EVREQ_FALLING ;
101
+
102
+ global_config = (chip -> evcap_config | chip -> trig_config );
103
+ err = mv88e6xxx_tai_write (chip , MV88E6XXX_TAI_CFG , global_config );
104
+ if (err )
105
+ return err ;
106
+
107
+ if (event == PTP_CLOCK_PPS ) {
108
+ cap_config = MV88E6XXX_TAI_EVENT_STATUS_CAP_TRIG ;
109
+ } else if (event == PTP_CLOCK_EXTTS ) {
110
+ /* if STATUS_CAP_TRIG is unset we capture PTP_EVREQ events */
111
+ cap_config = 0 ;
112
+ } else {
113
+ return - EINVAL ;
114
+ }
115
+
116
+ /* Write the capture config; this also clears the capture counter */
117
+ err = mv88e6xxx_tai_write (chip , MV88E6XXX_TAI_EVENT_STATUS ,
118
+ cap_config );
119
+
120
+ return err ;
121
+ }
122
+
123
+ static void mv88e6xxx_tai_event_work (struct work_struct * ugly )
124
+ {
125
+ struct delayed_work * dw = to_delayed_work (ugly );
126
+ struct mv88e6xxx_chip * chip = dw_tai_event_to_chip (dw );
127
+ struct ptp_clock_event ev ;
128
+ u16 status [4 ];
129
+ u32 raw_ts ;
130
+ int err ;
131
+
132
+ mutex_lock (& chip -> reg_lock );
133
+ err = mv88e6xxx_tai_read (chip , MV88E6XXX_TAI_EVENT_STATUS ,
134
+ status , ARRAY_SIZE (status ));
135
+ mutex_unlock (& chip -> reg_lock );
136
+
137
+ if (err ) {
138
+ dev_err (chip -> dev , "failed to read TAI status register\n" );
139
+ return ;
140
+ }
141
+ if (status [0 ] & MV88E6XXX_TAI_EVENT_STATUS_ERROR ) {
142
+ dev_warn (chip -> dev , "missed event capture\n" );
143
+ return ;
144
+ }
145
+ if (!(status [0 ] & MV88E6XXX_TAI_EVENT_STATUS_VALID ))
146
+ goto out ;
147
+
148
+ raw_ts = ((u32 )status [2 ] << 16 ) | status [1 ];
149
+
150
+ /* Clear the valid bit so the next timestamp can come in */
151
+ status [0 ] &= ~MV88E6XXX_TAI_EVENT_STATUS_VALID ;
152
+ mutex_lock (& chip -> reg_lock );
153
+ err = mv88e6xxx_tai_write (chip , MV88E6XXX_TAI_EVENT_STATUS , status [0 ]);
154
+ mutex_unlock (& chip -> reg_lock );
155
+
156
+ /* This is an external timestamp */
157
+ ev .type = PTP_CLOCK_EXTTS ;
158
+
159
+ /* We only have one timestamping channel. */
160
+ ev .index = 0 ;
161
+ mutex_lock (& chip -> reg_lock );
162
+ ev .timestamp = timecounter_cyc2time (& chip -> tstamp_tc , raw_ts );
163
+ mutex_unlock (& chip -> reg_lock );
164
+
165
+ ptp_clock_event (chip -> ptp_clock , & ev );
166
+ out :
167
+ schedule_delayed_work (& chip -> tai_event_work , TAI_EVENT_WORK_INTERVAL );
168
+ }
169
+
58
170
static int mv88e6xxx_ptp_adjfine (struct ptp_clock_info * ptp , long scaled_ppm )
59
171
{
60
172
struct mv88e6xxx_chip * chip = ptp_to_chip (ptp );
@@ -122,16 +234,71 @@ static int mv88e6xxx_ptp_settime(struct ptp_clock_info *ptp,
122
234
return 0 ;
123
235
}
124
236
237
+ static int mv88e6xxx_ptp_enable_extts (struct mv88e6xxx_chip * chip ,
238
+ struct ptp_clock_request * rq , int on )
239
+ {
240
+ int rising = (rq -> extts .flags & PTP_RISING_EDGE );
241
+ int func ;
242
+ int pin ;
243
+ int err ;
244
+
245
+ pin = ptp_find_pin (chip -> ptp_clock , PTP_PF_EXTTS , rq -> extts .index );
246
+
247
+ if (pin < 0 )
248
+ return - EBUSY ;
249
+
250
+ mutex_lock (& chip -> reg_lock );
251
+
252
+ if (on ) {
253
+ func = MV88E6352_G2_SCRATCH_GPIO_PCTL_EVREQ ;
254
+
255
+ err = mv88e6xxx_set_gpio_func (chip , pin , func , true);
256
+ if (err )
257
+ goto out ;
258
+
259
+ schedule_delayed_work (& chip -> tai_event_work ,
260
+ TAI_EVENT_WORK_INTERVAL );
261
+
262
+ err = mv88e6xxx_config_eventcap (chip , PTP_CLOCK_EXTTS , rising );
263
+ } else {
264
+ func = MV88E6352_G2_SCRATCH_GPIO_PCTL_GPIO ;
265
+
266
+ err = mv88e6xxx_set_gpio_func (chip , pin , func , true);
267
+
268
+ cancel_delayed_work_sync (& chip -> tai_event_work );
269
+ }
270
+
271
+ out :
272
+ mutex_unlock (& chip -> reg_lock );
273
+
274
+ return err ;
275
+ }
276
+
125
277
static int mv88e6xxx_ptp_enable (struct ptp_clock_info * ptp ,
126
278
struct ptp_clock_request * rq , int on )
127
279
{
128
- return - EOPNOTSUPP ;
280
+ struct mv88e6xxx_chip * chip = ptp_to_chip (ptp );
281
+
282
+ switch (rq -> type ) {
283
+ case PTP_CLK_REQ_EXTTS :
284
+ return mv88e6xxx_ptp_enable_extts (chip , rq , on );
285
+ default :
286
+ return - EOPNOTSUPP ;
287
+ }
129
288
}
130
289
131
290
static int mv88e6xxx_ptp_verify (struct ptp_clock_info * ptp , unsigned int pin ,
132
291
enum ptp_pin_function func , unsigned int chan )
133
292
{
134
- return - EOPNOTSUPP ;
293
+ switch (func ) {
294
+ case PTP_PF_NONE :
295
+ case PTP_PF_EXTTS :
296
+ break ;
297
+ case PTP_PF_PEROUT :
298
+ case PTP_PF_PHYSYNC :
299
+ return - EOPNOTSUPP ;
300
+ }
301
+ return 0 ;
135
302
}
136
303
137
304
/* With a 125MHz input clock, the 32-bit timestamp counter overflows in ~34.3
@@ -152,6 +319,8 @@ static void mv88e6xxx_ptp_overflow_check(struct work_struct *work)
152
319
153
320
int mv88e6xxx_ptp_setup (struct mv88e6xxx_chip * chip )
154
321
{
322
+ int i ;
323
+
155
324
/* Set up the cycle counter */
156
325
memset (& chip -> tstamp_cc , 0 , sizeof (chip -> tstamp_cc ));
157
326
chip -> tstamp_cc .read = mv88e6xxx_ptp_clock_read ;
@@ -163,12 +332,27 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
163
332
ktime_to_ns (ktime_get_real ()));
164
333
165
334
INIT_DELAYED_WORK (& chip -> overflow_work , mv88e6xxx_ptp_overflow_check );
335
+ INIT_DELAYED_WORK (& chip -> tai_event_work , mv88e6xxx_tai_event_work );
166
336
167
337
chip -> ptp_clock_info .owner = THIS_MODULE ;
168
338
snprintf (chip -> ptp_clock_info .name , sizeof (chip -> ptp_clock_info .name ),
169
339
dev_name (chip -> dev ));
170
340
chip -> ptp_clock_info .max_adj = 1000000 ;
171
341
342
+ chip -> ptp_clock_info .n_ext_ts = 1 ;
343
+ chip -> ptp_clock_info .n_per_out = 0 ;
344
+ chip -> ptp_clock_info .n_pins = mv88e6xxx_num_gpio (chip );
345
+ chip -> ptp_clock_info .pps = 0 ;
346
+
347
+ for (i = 0 ; i < chip -> ptp_clock_info .n_pins ; ++ i ) {
348
+ struct ptp_pin_desc * ppd = & chip -> pin_config [i ];
349
+
350
+ snprintf (ppd -> name , sizeof (ppd -> name ), "mv88e6xxx_gpio%d" , i );
351
+ ppd -> index = i ;
352
+ ppd -> func = PTP_PF_NONE ;
353
+ }
354
+ chip -> ptp_clock_info .pin_config = chip -> pin_config ;
355
+
172
356
chip -> ptp_clock_info .adjfine = mv88e6xxx_ptp_adjfine ;
173
357
chip -> ptp_clock_info .adjtime = mv88e6xxx_ptp_adjtime ;
174
358
chip -> ptp_clock_info .gettime64 = mv88e6xxx_ptp_gettime ;
@@ -190,6 +374,7 @@ void mv88e6xxx_ptp_free(struct mv88e6xxx_chip *chip)
190
374
{
191
375
if (chip -> ptp_clock ) {
192
376
cancel_delayed_work_sync (& chip -> overflow_work );
377
+ cancel_delayed_work_sync (& chip -> tai_event_work );
193
378
194
379
ptp_clock_unregister (chip -> ptp_clock );
195
380
chip -> ptp_clock = NULL ;
0 commit comments