@@ -54,6 +54,243 @@ static int mchp_rds_phy_set_bits_mmd(struct mchp_rds_ptp_clock *clock,
54
54
return phy_set_bits_mmd (phydev , PTP_MMD (clock ), addr , val );
55
55
}
56
56
57
+ static int mchp_get_pulsewidth (struct phy_device * phydev ,
58
+ struct ptp_perout_request * perout_request ,
59
+ int * pulse_width )
60
+ {
61
+ struct timespec64 ts_period ;
62
+ s64 ts_on_nsec , period_nsec ;
63
+ struct timespec64 ts_on ;
64
+ static const s64 sup_on_necs [] = {
65
+ 100 , /* 100ns */
66
+ 500 , /* 500ns */
67
+ 1000 , /* 1us */
68
+ 5000 , /* 5us */
69
+ 10000 , /* 10us */
70
+ 50000 , /* 50us */
71
+ 100000 , /* 100us */
72
+ 500000 , /* 500us */
73
+ 1000000 , /* 1ms */
74
+ 5000000 , /* 5ms */
75
+ 10000000 , /* 10ms */
76
+ 50000000 , /* 50ms */
77
+ 100000000 , /* 100ms */
78
+ 200000000 , /* 200ms */
79
+ };
80
+
81
+ ts_period .tv_sec = perout_request -> period .sec ;
82
+ ts_period .tv_nsec = perout_request -> period .nsec ;
83
+
84
+ ts_on .tv_sec = perout_request -> on .sec ;
85
+ ts_on .tv_nsec = perout_request -> on .nsec ;
86
+ ts_on_nsec = timespec64_to_ns (& ts_on );
87
+ period_nsec = timespec64_to_ns (& ts_period );
88
+
89
+ if (period_nsec < 200 ) {
90
+ phydev_warn (phydev , "perout period small, minimum is 200ns\n" );
91
+ return - EOPNOTSUPP ;
92
+ }
93
+
94
+ for (int i = 0 ; i < ARRAY_SIZE (sup_on_necs ); i ++ ) {
95
+ if (ts_on_nsec <= sup_on_necs [i ]) {
96
+ * pulse_width = i ;
97
+ break ;
98
+ }
99
+ }
100
+
101
+ phydev_info (phydev , "pulse width is %d\n" , * pulse_width );
102
+ return 0 ;
103
+ }
104
+
105
+ static int mchp_general_event_config (struct mchp_rds_ptp_clock * clock ,
106
+ int pulse_width )
107
+ {
108
+ int general_config ;
109
+
110
+ general_config = mchp_rds_phy_read_mmd (clock , MCHP_RDS_PTP_GEN_CFG ,
111
+ MCHP_RDS_PTP_CLOCK );
112
+ if (general_config < 0 )
113
+ return general_config ;
114
+
115
+ general_config &= ~MCHP_RDS_PTP_GEN_CFG_LTC_EVT_MASK ;
116
+ general_config |= MCHP_RDS_PTP_GEN_CFG_LTC_EVT_SET (pulse_width );
117
+ general_config &= ~MCHP_RDS_PTP_GEN_CFG_RELOAD_ADD ;
118
+ general_config |= MCHP_RDS_PTP_GEN_CFG_POLARITY ;
119
+
120
+ return mchp_rds_phy_write_mmd (clock , MCHP_RDS_PTP_GEN_CFG ,
121
+ MCHP_RDS_PTP_CLOCK , general_config );
122
+ }
123
+
124
+ static int mchp_set_clock_reload (struct mchp_rds_ptp_clock * clock ,
125
+ s64 period_sec , u32 period_nsec )
126
+ {
127
+ int rc ;
128
+
129
+ rc = mchp_rds_phy_write_mmd (clock ,
130
+ MCHP_RDS_PTP_CLK_TRGT_RELOAD_SEC_LO ,
131
+ MCHP_RDS_PTP_CLOCK ,
132
+ lower_16_bits (period_sec ));
133
+ if (rc < 0 )
134
+ return rc ;
135
+
136
+ rc = mchp_rds_phy_write_mmd (clock ,
137
+ MCHP_RDS_PTP_CLK_TRGT_RELOAD_SEC_HI ,
138
+ MCHP_RDS_PTP_CLOCK ,
139
+ upper_16_bits (period_sec ));
140
+ if (rc < 0 )
141
+ return rc ;
142
+
143
+ rc = mchp_rds_phy_write_mmd (clock ,
144
+ MCHP_RDS_PTP_CLK_TRGT_RELOAD_NS_LO ,
145
+ MCHP_RDS_PTP_CLOCK ,
146
+ lower_16_bits (period_nsec ));
147
+ if (rc < 0 )
148
+ return rc ;
149
+
150
+ return mchp_rds_phy_write_mmd (clock ,
151
+ MCHP_RDS_PTP_CLK_TRGT_RELOAD_NS_HI ,
152
+ MCHP_RDS_PTP_CLOCK ,
153
+ upper_16_bits (period_nsec ) & 0x3fff );
154
+ }
155
+
156
+ static int mchp_set_clock_target (struct mchp_rds_ptp_clock * clock ,
157
+ s64 start_sec , u32 start_nsec )
158
+ {
159
+ int rc ;
160
+
161
+ /* Set the start time */
162
+ rc = mchp_rds_phy_write_mmd (clock , MCHP_RDS_PTP_CLK_TRGT_SEC_LO ,
163
+ MCHP_RDS_PTP_CLOCK ,
164
+ lower_16_bits (start_sec ));
165
+ if (rc < 0 )
166
+ return rc ;
167
+
168
+ rc = mchp_rds_phy_write_mmd (clock , MCHP_RDS_PTP_CLK_TRGT_SEC_HI ,
169
+ MCHP_RDS_PTP_CLOCK ,
170
+ upper_16_bits (start_sec ));
171
+ if (rc < 0 )
172
+ return rc ;
173
+
174
+ rc = mchp_rds_phy_write_mmd (clock , MCHP_RDS_PTP_CLK_TRGT_NS_LO ,
175
+ MCHP_RDS_PTP_CLOCK ,
176
+ lower_16_bits (start_nsec ));
177
+ if (rc < 0 )
178
+ return rc ;
179
+
180
+ return mchp_rds_phy_write_mmd (clock , MCHP_RDS_PTP_CLK_TRGT_NS_HI ,
181
+ MCHP_RDS_PTP_CLOCK ,
182
+ upper_16_bits (start_nsec ) & 0x3fff );
183
+ }
184
+
185
+ static int mchp_rds_ptp_perout_off (struct mchp_rds_ptp_clock * clock )
186
+ {
187
+ u16 general_config ;
188
+ int rc ;
189
+
190
+ /* Set target to too far in the future, effectively disabling it */
191
+ rc = mchp_set_clock_target (clock , 0xFFFFFFFF , 0 );
192
+ if (rc < 0 )
193
+ return rc ;
194
+
195
+ general_config = mchp_rds_phy_read_mmd (clock , MCHP_RDS_PTP_GEN_CFG ,
196
+ MCHP_RDS_PTP_CLOCK );
197
+ general_config |= MCHP_RDS_PTP_GEN_CFG_RELOAD_ADD ;
198
+ rc = mchp_rds_phy_write_mmd (clock , MCHP_RDS_PTP_GEN_CFG ,
199
+ MCHP_RDS_PTP_CLOCK , general_config );
200
+ if (rc < 0 )
201
+ return rc ;
202
+
203
+ clock -> mchp_rds_ptp_event = -1 ;
204
+
205
+ return 0 ;
206
+ }
207
+
208
+ static bool mchp_get_event (struct mchp_rds_ptp_clock * clock , int pin )
209
+ {
210
+ if (clock -> mchp_rds_ptp_event < 0 && pin == clock -> event_pin ) {
211
+ clock -> mchp_rds_ptp_event = pin ;
212
+ return true;
213
+ }
214
+
215
+ return false;
216
+ }
217
+
218
+ static int mchp_rds_ptp_perout (struct ptp_clock_info * ptpci ,
219
+ struct ptp_perout_request * perout , int on )
220
+ {
221
+ struct mchp_rds_ptp_clock * clock = container_of (ptpci ,
222
+ struct mchp_rds_ptp_clock ,
223
+ caps );
224
+ struct phy_device * phydev = clock -> phydev ;
225
+ int ret , event_pin , pulsewidth ;
226
+
227
+ /* Reject requests with unsupported flags */
228
+ if (perout -> flags & ~PTP_PEROUT_DUTY_CYCLE )
229
+ return - EOPNOTSUPP ;
230
+
231
+ event_pin = ptp_find_pin (clock -> ptp_clock , PTP_PF_PEROUT ,
232
+ perout -> index );
233
+ if (event_pin != clock -> event_pin )
234
+ return - EINVAL ;
235
+
236
+ if (!on ) {
237
+ ret = mchp_rds_ptp_perout_off (clock );
238
+ return ret ;
239
+ }
240
+
241
+ if (!mchp_get_event (clock , event_pin ))
242
+ return - EINVAL ;
243
+
244
+ ret = mchp_get_pulsewidth (phydev , perout , & pulsewidth );
245
+ if (ret < 0 )
246
+ return ret ;
247
+
248
+ /* Configure to pulse every period */
249
+ ret = mchp_general_event_config (clock , pulsewidth );
250
+ if (ret < 0 )
251
+ return ret ;
252
+
253
+ ret = mchp_set_clock_target (clock , perout -> start .sec ,
254
+ perout -> start .nsec );
255
+ if (ret < 0 )
256
+ return ret ;
257
+
258
+ return mchp_set_clock_reload (clock , perout -> period .sec ,
259
+ perout -> period .nsec );
260
+ }
261
+
262
+ static int mchp_rds_ptpci_enable (struct ptp_clock_info * ptpci ,
263
+ struct ptp_clock_request * request , int on )
264
+ {
265
+ switch (request -> type ) {
266
+ case PTP_CLK_REQ_PEROUT :
267
+ return mchp_rds_ptp_perout (ptpci , & request -> perout , on );
268
+ default :
269
+ return - EINVAL ;
270
+ }
271
+ }
272
+
273
+ static int mchp_rds_ptpci_verify (struct ptp_clock_info * ptpci , unsigned int pin ,
274
+ enum ptp_pin_function func , unsigned int chan )
275
+ {
276
+ struct mchp_rds_ptp_clock * clock = container_of (ptpci ,
277
+ struct mchp_rds_ptp_clock ,
278
+ caps );
279
+
280
+ if (!(pin == clock -> event_pin && chan == 0 ))
281
+ return -1 ;
282
+
283
+ switch (func ) {
284
+ case PTP_PF_NONE :
285
+ case PTP_PF_PEROUT :
286
+ break ;
287
+ default :
288
+ return -1 ;
289
+ }
290
+
291
+ return 0 ;
292
+ }
293
+
57
294
static int mchp_rds_ptp_flush_fifo (struct mchp_rds_ptp_clock * clock ,
58
295
enum mchp_rds_ptp_fifo_dir dir )
59
296
{
@@ -479,6 +716,16 @@ static int mchp_rds_ptp_ltc_adjtime(struct ptp_clock_info *info, s64 delta)
479
716
MCHP_RDS_PTP_CMD_CTL_LTC_STEP_NSEC );
480
717
}
481
718
719
+ mutex_unlock (& clock -> ptp_lock );
720
+ info -> gettime64 (info , & ts );
721
+ mutex_lock (& clock -> ptp_lock );
722
+
723
+ /* Target update is required for pulse generation on events that
724
+ * are enabled
725
+ */
726
+ if (clock -> mchp_rds_ptp_event >= 0 )
727
+ mchp_set_clock_target (clock ,
728
+ ts .tv_sec + MCHP_RDS_PTP_BUFFER_TIME , 0 );
482
729
out_unlock :
483
730
mutex_unlock (& clock -> ptp_lock );
484
731
@@ -989,16 +1236,37 @@ struct mchp_rds_ptp_clock *mchp_rds_ptp_probe(struct phy_device *phydev, u8 mmd,
989
1236
clock -> mmd = mmd ;
990
1237
991
1238
mutex_init (& clock -> ptp_lock );
1239
+ clock -> pin_config = devm_kmalloc_array (& phydev -> mdio .dev ,
1240
+ MCHP_RDS_PTP_N_PIN ,
1241
+ sizeof (* clock -> pin_config ),
1242
+ GFP_KERNEL );
1243
+ if (!clock -> pin_config )
1244
+ return ERR_PTR (- ENOMEM );
1245
+
1246
+ for (int i = 0 ; i < MCHP_RDS_PTP_N_PIN ; ++ i ) {
1247
+ struct ptp_pin_desc * p = & clock -> pin_config [i ];
1248
+
1249
+ memset (p , 0 , sizeof (* p ));
1250
+ snprintf (p -> name , sizeof (p -> name ), "pin%d" , i );
1251
+ p -> index = i ;
1252
+ p -> func = PTP_PF_NONE ;
1253
+ }
992
1254
/* Register PTP clock */
993
1255
clock -> caps .owner = THIS_MODULE ;
994
1256
snprintf (clock -> caps .name , 30 , "%s" , phydev -> drv -> name );
995
1257
clock -> caps .max_adj = MCHP_RDS_PTP_MAX_ADJ ;
996
1258
clock -> caps .n_ext_ts = 0 ;
997
1259
clock -> caps .pps = 0 ;
1260
+ clock -> caps .n_pins = MCHP_RDS_PTP_N_PIN ;
1261
+ clock -> caps .n_per_out = MCHP_RDS_PTP_N_PEROUT ;
1262
+ clock -> caps .pin_config = clock -> pin_config ;
998
1263
clock -> caps .adjfine = mchp_rds_ptp_ltc_adjfine ;
999
1264
clock -> caps .adjtime = mchp_rds_ptp_ltc_adjtime ;
1000
1265
clock -> caps .gettime64 = mchp_rds_ptp_ltc_gettime64 ;
1001
1266
clock -> caps .settime64 = mchp_rds_ptp_ltc_settime64 ;
1267
+ clock -> caps .enable = mchp_rds_ptpci_enable ;
1268
+ clock -> caps .verify = mchp_rds_ptpci_verify ;
1269
+ clock -> caps .getcrosststamp = NULL ;
1002
1270
clock -> ptp_clock = ptp_clock_register (& clock -> caps ,
1003
1271
& phydev -> mdio .dev );
1004
1272
if (IS_ERR (clock -> ptp_clock ))
@@ -1021,6 +1289,8 @@ struct mchp_rds_ptp_clock *mchp_rds_ptp_probe(struct phy_device *phydev, u8 mmd,
1021
1289
1022
1290
phydev -> mii_ts = & clock -> mii_ts ;
1023
1291
1292
+ clock -> mchp_rds_ptp_event = -1 ;
1293
+
1024
1294
/* Timestamp selected by default to keep legacy API */
1025
1295
phydev -> default_timestamp = true;
1026
1296
0 commit comments