1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#include <linux/io.h>
27#include <linux/delay.h>
28#include "common.h"
29#include "stmmac_ptp.h"
30
31static void stmmac_config_hw_tstamping(void __iomem *ioaddr, u32 data)
32{
33 writel(data, ioaddr + PTP_TCR);
34}
35
36static void stmmac_config_sub_second_increment(void __iomem *ioaddr)
37{
38 u32 value = readl(ioaddr + PTP_TCR);
39 unsigned long data;
40
41
42
43
44
45 data = (1000000000ULL / 50000000);
46
47
48 if (value & PTP_TCR_TSCTRLSSR)
49 data = (data * 100) / 465;
50
51 writel(data, ioaddr + PTP_SSIR);
52}
53
54static int stmmac_init_systime(void __iomem *ioaddr, u32 sec, u32 nsec)
55{
56 int limit;
57 u32 value;
58
59 writel(sec, ioaddr + PTP_STSUR);
60 writel(nsec, ioaddr + PTP_STNSUR);
61
62 value = readl(ioaddr + PTP_TCR);
63 value |= PTP_TCR_TSINIT;
64 writel(value, ioaddr + PTP_TCR);
65
66
67 limit = 10;
68 while (limit--) {
69 if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSINIT))
70 break;
71 mdelay(10);
72 }
73 if (limit < 0)
74 return -EBUSY;
75
76 return 0;
77}
78
79static int stmmac_config_addend(void __iomem *ioaddr, u32 addend)
80{
81 u32 value;
82 int limit;
83
84 writel(addend, ioaddr + PTP_TAR);
85
86 value = readl(ioaddr + PTP_TCR);
87 value |= PTP_TCR_TSADDREG;
88 writel(value, ioaddr + PTP_TCR);
89
90
91 limit = 10;
92 while (limit--) {
93 if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSADDREG))
94 break;
95 mdelay(10);
96 }
97 if (limit < 0)
98 return -EBUSY;
99
100 return 0;
101}
102
103static int stmmac_adjust_systime(void __iomem *ioaddr, u32 sec, u32 nsec,
104 int add_sub)
105{
106 u32 value;
107 int limit;
108
109 writel(sec, ioaddr + PTP_STSUR);
110 writel(((add_sub << PTP_STNSUR_ADDSUB_SHIFT) | nsec),
111 ioaddr + PTP_STNSUR);
112
113 value = readl(ioaddr + PTP_TCR);
114 value |= PTP_TCR_TSUPDT;
115 writel(value, ioaddr + PTP_TCR);
116
117
118 limit = 10;
119 while (limit--) {
120 if (!(readl(ioaddr + PTP_TCR) & PTP_TCR_TSUPDT))
121 break;
122 mdelay(10);
123 }
124 if (limit < 0)
125 return -EBUSY;
126
127 return 0;
128}
129
130static u64 stmmac_get_systime(void __iomem *ioaddr)
131{
132 u64 ns;
133
134 ns = readl(ioaddr + PTP_STNSR);
135
136 ns += readl(ioaddr + PTP_STSR) * 1000000000ULL;
137
138 return ns;
139}
140
141const struct stmmac_hwtimestamp stmmac_ptp = {
142 .config_hw_tstamping = stmmac_config_hw_tstamping,
143 .init_systime = stmmac_init_systime,
144 .config_sub_second_increment = stmmac_config_sub_second_increment,
145 .config_addend = stmmac_config_addend,
146 .adjust_systime = stmmac_adjust_systime,
147 .get_systime = stmmac_get_systime,
148};
149