14
14
#include <linux/of.h>
15
15
#include <linux/of_platform.h>
16
16
#include <linux/platform_device.h>
17
+ #include <linux/timecounter.h>
18
+ #include <linux/clocksource.h>
17
19
#include <linux/timekeeping.h>
18
20
#include <linux/interrupt.h>
19
21
#include <linux/of_irq.h>
20
22
#include <linux/workqueue.h>
21
23
22
24
#include "icss_iep.h"
25
+ #include "../icssm/icssm_prueth_ptp.h"
23
26
24
27
#define IEP_MAX_DEF_INC 0xf
25
28
#define IEP_MAX_COMPEN_INC 0xfff
53
56
#define IEP_CAP_CFG_CAPNR_1ST_EVENT_EN (n ) BIT(LATCH_INDEX(n))
54
57
#define IEP_CAP_CFG_CAP_ASYNC_EN (n ) BIT(LATCH_INDEX(n) + 10)
55
58
59
+ #define IEP_TC_DEFAULT_SHIFT 28
60
+ #define IEP_TC_INCR5_MULT BIT(28)
61
+
62
+ /* Polling period - how often iep_overflow_check() is called */
63
+ #define IEP_OVERFLOW_CHECK_PERIOD_MS 50
64
+
65
+ #define TIMESYNC_SECONDS_COUNT_SIZE 6
66
+
56
67
/**
57
68
* icss_iep_get_count_hi() - Get the upper 32 bit IEP counter
58
69
* @iep: Pointer to structure representing IEP.
@@ -87,6 +98,28 @@ int icss_iep_get_count_low(struct icss_iep *iep)
87
98
}
88
99
EXPORT_SYMBOL_GPL (icss_iep_get_count_low );
89
100
101
+ static u64 icss_iep_get_count32 (struct icss_iep * iep )
102
+ {
103
+ void __iomem * sram = iep -> sram ;
104
+ u64 v_sec = 0 ;
105
+ u32 v_ns = 0 ;
106
+ u64 v = 0 ;
107
+
108
+ v_ns = icss_iep_get_count_low (iep );
109
+ memcpy_fromio (& v_sec , sram + TIMESYNC_SECONDS_COUNT_OFFSET ,
110
+ TIMESYNC_SECONDS_COUNT_SIZE );
111
+ v = (v_sec * NSEC_PER_SEC ) + v_ns ;
112
+
113
+ return v ;
114
+ }
115
+
116
+ static u64 icss_iep_cc_read (const struct cyclecounter * cc )
117
+ {
118
+ struct icss_iep * iep = container_of (cc , struct icss_iep , cc );
119
+
120
+ return icss_iep_get_count32 (iep );
121
+ }
122
+
90
123
/**
91
124
* icss_iep_get_ptp_clock_idx() - Get PTP clock index using IEP driver
92
125
* @iep: Pointer to structure representing IEP.
@@ -280,6 +313,78 @@ static void icss_iep_set_slow_compensation_count(struct icss_iep *iep,
280
313
regmap_write (iep -> map , ICSS_IEP_SLOW_COMPEN_REG , compen_count );
281
314
}
282
315
316
+ /* PTP PHC operations */
317
+ static int icss_iep_ptp_adjfine_v1 (struct ptp_clock_info * ptp , long scaled_ppm )
318
+ {
319
+ struct icss_iep * iep = container_of (ptp , struct icss_iep , ptp_info );
320
+ s32 ppb = scaled_ppm_to_ppb (scaled_ppm );
321
+ struct timespec64 ts ;
322
+ int neg_adj = 0 ;
323
+ u32 diff , mult ;
324
+ u64 adj ;
325
+
326
+ mutex_lock (& iep -> ptp_clk_mutex );
327
+
328
+ if (ppb < 0 ) {
329
+ neg_adj = 1 ;
330
+ ppb = - ppb ;
331
+ }
332
+ mult = iep -> cc_mult ;
333
+ adj = mult ;
334
+ adj *= ppb ;
335
+ diff = div_u64 (adj , 1000000000ULL );
336
+
337
+ ts = ns_to_timespec64 (timecounter_read (& iep -> tc ));
338
+ pr_debug ("iep ptp adjfine check at %lld.%09lu\n" , ts .tv_sec ,
339
+ ts .tv_nsec );
340
+
341
+ iep -> cc .mult = neg_adj ? mult - diff : mult + diff ;
342
+
343
+ mutex_unlock (& iep -> ptp_clk_mutex );
344
+
345
+ return 0 ;
346
+ }
347
+
348
+ static int icss_iep_ptp_adjtime_v1 (struct ptp_clock_info * ptp , s64 delta )
349
+ {
350
+ struct icss_iep * iep = container_of (ptp , struct icss_iep , ptp_info );
351
+
352
+ mutex_lock (& iep -> ptp_clk_mutex );
353
+ timecounter_adjtime (& iep -> tc , delta );
354
+ mutex_unlock (& iep -> ptp_clk_mutex );
355
+
356
+ return 0 ;
357
+ }
358
+
359
+ static int icss_iep_ptp_gettimeex_v1 (struct ptp_clock_info * ptp ,
360
+ struct timespec64 * ts ,
361
+ struct ptp_system_timestamp * sts )
362
+ {
363
+ struct icss_iep * iep = container_of (ptp , struct icss_iep , ptp_info );
364
+ u64 ns ;
365
+
366
+ mutex_lock (& iep -> ptp_clk_mutex );
367
+ ns = timecounter_read (& iep -> tc );
368
+ * ts = ns_to_timespec64 (ns );
369
+ mutex_unlock (& iep -> ptp_clk_mutex );
370
+
371
+ return 0 ;
372
+ }
373
+
374
+ static int icss_iep_ptp_settime_v1 (struct ptp_clock_info * ptp ,
375
+ const struct timespec64 * ts )
376
+ {
377
+ struct icss_iep * iep = container_of (ptp , struct icss_iep , ptp_info );
378
+ u64 ns ;
379
+
380
+ mutex_lock (& iep -> ptp_clk_mutex );
381
+ ns = timespec64_to_ns (ts );
382
+ timecounter_init (& iep -> tc , & iep -> cc , ns );
383
+ mutex_unlock (& iep -> ptp_clk_mutex );
384
+
385
+ return 0 ;
386
+ }
387
+
283
388
/* PTP PHC operations */
284
389
static int icss_iep_ptp_adjfine (struct ptp_clock_info * ptp , long scaled_ppm )
285
390
{
@@ -669,6 +774,17 @@ static int icss_iep_ptp_enable(struct ptp_clock_info *ptp,
669
774
return - EOPNOTSUPP ;
670
775
}
671
776
777
+ static long icss_iep_overflow_check (struct ptp_clock_info * ptp )
778
+ {
779
+ struct icss_iep * iep = container_of (ptp , struct icss_iep , ptp_info );
780
+ unsigned long delay = iep -> ovfl_check_period ;
781
+ struct timespec64 ts ;
782
+
783
+ ts = ns_to_timespec64 (timecounter_read (& iep -> tc ));
784
+
785
+ pr_debug ("iep overflow check at %lld.%09lu\n" , ts .tv_sec , ts .tv_nsec );
786
+ return (long )delay ;
787
+ }
672
788
static struct ptp_clock_info icss_iep_ptp_info = {
673
789
.owner = THIS_MODULE ,
674
790
.name = "ICSS IEP timer" ,
@@ -680,6 +796,18 @@ static struct ptp_clock_info icss_iep_ptp_info = {
680
796
.enable = icss_iep_ptp_enable ,
681
797
};
682
798
799
+ static struct ptp_clock_info icss_iep_ptp_info_v1 = {
800
+ .owner = THIS_MODULE ,
801
+ .name = "ICSS IEP timer" ,
802
+ .max_adj = 10000000 ,
803
+ .adjfine = icss_iep_ptp_adjfine_v1 ,
804
+ .adjtime = icss_iep_ptp_adjtime_v1 ,
805
+ .gettimex64 = icss_iep_ptp_gettimeex_v1 ,
806
+ .settime64 = icss_iep_ptp_settime_v1 ,
807
+ .enable = icss_iep_ptp_enable ,
808
+ .do_aux_work = icss_iep_overflow_check ,
809
+ };
810
+
683
811
struct icss_iep * icss_iep_get_idx (struct device_node * np , int idx )
684
812
{
685
813
struct platform_device * pdev ;
@@ -701,6 +829,18 @@ struct icss_iep *icss_iep_get_idx(struct device_node *np, int idx)
701
829
if (!iep )
702
830
return ERR_PTR (- EPROBE_DEFER );
703
831
832
+ if (iep -> plat_data -> iep_rev == IEP_REV_V1_0 ) {
833
+ iep -> cc .shift = IEP_TC_DEFAULT_SHIFT ;
834
+ iep -> cc .mult = IEP_TC_INCR5_MULT ;
835
+
836
+ iep -> cc .read = icss_iep_cc_read ;
837
+ iep -> cc .mask = CLOCKSOURCE_MASK (64 );
838
+
839
+ iep -> ovfl_check_period =
840
+ msecs_to_jiffies (IEP_OVERFLOW_CHECK_PERIOD_MS );
841
+ iep -> cc_mult = iep -> cc .mult ;
842
+ }
843
+
704
844
device_lock (iep -> dev );
705
845
if (iep -> client_np ) {
706
846
device_unlock (iep -> dev );
@@ -795,13 +935,20 @@ int icss_iep_init(struct icss_iep *iep, const struct icss_iep_clockops *clkops,
795
935
icss_iep_enable (iep );
796
936
icss_iep_settime (iep , ktime_get_real_ns ());
797
937
938
+ if (iep -> plat_data -> iep_rev == IEP_REV_V1_0 )
939
+ timecounter_init (& iep -> tc , & iep -> cc ,
940
+ ktime_to_ns (ktime_get_real ()));
941
+
798
942
iep -> ptp_clock = ptp_clock_register (& iep -> ptp_info , iep -> dev );
799
943
if (IS_ERR (iep -> ptp_clock )) {
800
944
ret = PTR_ERR (iep -> ptp_clock );
801
945
iep -> ptp_clock = NULL ;
802
946
dev_err (iep -> dev , "Failed to register ptp clk %d\n" , ret );
803
947
}
804
948
949
+ if (iep -> plat_data -> iep_rev == IEP_REV_V1_0 )
950
+ ptp_schedule_worker (iep -> ptp_clock , iep -> ovfl_check_period );
951
+
805
952
return ret ;
806
953
}
807
954
EXPORT_SYMBOL_GPL (icss_iep_init );
@@ -879,7 +1026,11 @@ static int icss_iep_probe(struct platform_device *pdev)
879
1026
return PTR_ERR (iep -> map );
880
1027
}
881
1028
882
- iep -> ptp_info = icss_iep_ptp_info ;
1029
+ if (iep -> plat_data -> iep_rev == IEP_REV_V1_0 )
1030
+ iep -> ptp_info = icss_iep_ptp_info_v1 ;
1031
+ else
1032
+ iep -> ptp_info = icss_iep_ptp_info ;
1033
+
883
1034
mutex_init (& iep -> ptp_clk_mutex );
884
1035
dev_set_drvdata (dev , iep );
885
1036
icss_iep_disable (iep );
@@ -1004,6 +1155,7 @@ static const struct icss_iep_plat_data am57xx_icss_iep_plat_data = {
1004
1155
[ICSS_IEP_SYNC_START_REG ] = 0x19c ,
1005
1156
},
1006
1157
.config = & am654_icss_iep_regmap_config ,
1158
+ .iep_rev = IEP_REV_V2_1 ,
1007
1159
};
1008
1160
1009
1161
static bool am335x_icss_iep_valid_reg (struct device * dev , unsigned int reg )
@@ -1057,6 +1209,7 @@ static const struct icss_iep_plat_data am335x_icss_iep_plat_data = {
1057
1209
[ICSS_IEP_SYNC_START_REG ] = 0x11C ,
1058
1210
},
1059
1211
.config = & am335x_icss_iep_regmap_config ,
1212
+ .iep_rev = IEP_REV_V1_0 ,
1060
1213
};
1061
1214
1062
1215
static const struct of_device_id icss_iep_of_match [] = {
0 commit comments