1 // SPDX-License-Identifier: GPL-2.0
2 /* Renesas R-Car Gen4 gPTP device driver
3 *
4 * Copyright (C) 2022 Renesas Electronics Corporation
5 */
6
7 #include <linux/err.h>
8 #include <linux/etherdevice.h>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/platform_device.h>
12 #include <linux/ptp_clock_kernel.h>
13 #include <linux/slab.h>
14
15 #include "rcar_gen4_ptp.h"
16
17 #define PTPTMEC_REG 0x0010
18 #define PTPTMDC_REG 0x0014
19 #define PTPTIVC0_REG 0x0020
20 #define PTPTOVC00_REG 0x0030
21 #define PTPTOVC10_REG 0x0034
22 #define PTPTOVC20_REG 0x0038
23 #define PTPGPTPTM00_REG 0x0050
24 #define PTPGPTPTM10_REG 0x0054
25 #define PTPGPTPTM20_REG 0x0058
26
27 struct rcar_gen4_ptp_private {
28 void __iomem *addr;
29 struct ptp_clock *clock;
30 struct ptp_clock_info info;
31 spinlock_t lock; /* For multiple registers access */
32 s64 default_addend;
33 bool initialized;
34 };
35
36 #define ptp_to_priv(ptp) container_of(ptp, struct rcar_gen4_ptp_private, info)
37
rcar_gen4_ptp_adjfine(struct ptp_clock_info * ptp,long scaled_ppm)38 static int rcar_gen4_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
39 {
40 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
41 s64 addend = ptp_priv->default_addend;
42 bool neg_adj = scaled_ppm < 0;
43 s64 diff;
44
45 if (neg_adj)
46 scaled_ppm = -scaled_ppm;
47 diff = div_s64(addend * scaled_ppm_to_ppb(scaled_ppm), NSEC_PER_SEC);
48 addend = neg_adj ? addend - diff : addend + diff;
49
50 iowrite32(addend, ptp_priv->addr + PTPTIVC0_REG);
51
52 return 0;
53 }
54
_rcar_gen4_ptp_gettime(struct ptp_clock_info * ptp,struct timespec64 * ts)55 static void _rcar_gen4_ptp_gettime(struct ptp_clock_info *ptp,
56 struct timespec64 *ts)
57 {
58 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
59
60 lockdep_assert_held(&ptp_priv->lock);
61
62 ts->tv_nsec = ioread32(ptp_priv->addr + PTPGPTPTM00_REG);
63 ts->tv_sec = ioread32(ptp_priv->addr + PTPGPTPTM10_REG) |
64 ((s64)ioread32(ptp_priv->addr + PTPGPTPTM20_REG) << 32);
65 }
66
rcar_gen4_ptp_gettime(struct ptp_clock_info * ptp,struct timespec64 * ts)67 static int rcar_gen4_ptp_gettime(struct ptp_clock_info *ptp,
68 struct timespec64 *ts)
69 {
70 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
71 unsigned long flags;
72
73 spin_lock_irqsave(&ptp_priv->lock, flags);
74 _rcar_gen4_ptp_gettime(ptp, ts);
75 spin_unlock_irqrestore(&ptp_priv->lock, flags);
76
77 return 0;
78 }
79
80 /* Caller must hold the lock */
_rcar_gen4_ptp_settime(struct ptp_clock_info * ptp,const struct timespec64 * ts)81 static void _rcar_gen4_ptp_settime(struct ptp_clock_info *ptp,
82 const struct timespec64 *ts)
83 {
84 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
85
86 iowrite32(1, ptp_priv->addr + PTPTMDC_REG);
87 iowrite32(0, ptp_priv->addr + PTPTOVC20_REG);
88 iowrite32(0, ptp_priv->addr + PTPTOVC10_REG);
89 iowrite32(0, ptp_priv->addr + PTPTOVC00_REG);
90 iowrite32(1, ptp_priv->addr + PTPTMEC_REG);
91 iowrite32(ts->tv_sec >> 32, ptp_priv->addr + PTPTOVC20_REG);
92 iowrite32(ts->tv_sec, ptp_priv->addr + PTPTOVC10_REG);
93 iowrite32(ts->tv_nsec, ptp_priv->addr + PTPTOVC00_REG);
94 }
95
rcar_gen4_ptp_settime(struct ptp_clock_info * ptp,const struct timespec64 * ts)96 static int rcar_gen4_ptp_settime(struct ptp_clock_info *ptp,
97 const struct timespec64 *ts)
98 {
99 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
100 unsigned long flags;
101
102 spin_lock_irqsave(&ptp_priv->lock, flags);
103 _rcar_gen4_ptp_settime(ptp, ts);
104 spin_unlock_irqrestore(&ptp_priv->lock, flags);
105
106 return 0;
107 }
108
rcar_gen4_ptp_adjtime(struct ptp_clock_info * ptp,s64 delta)109 static int rcar_gen4_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
110 {
111 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
112 struct timespec64 ts;
113 unsigned long flags;
114 s64 now;
115
116 spin_lock_irqsave(&ptp_priv->lock, flags);
117 _rcar_gen4_ptp_gettime(ptp, &ts);
118 now = ktime_to_ns(timespec64_to_ktime(ts));
119 ts = ns_to_timespec64(now + delta);
120 _rcar_gen4_ptp_settime(ptp, &ts);
121 spin_unlock_irqrestore(&ptp_priv->lock, flags);
122
123 return 0;
124 }
125
rcar_gen4_ptp_enable(struct ptp_clock_info * ptp,struct ptp_clock_request * rq,int on)126 static int rcar_gen4_ptp_enable(struct ptp_clock_info *ptp,
127 struct ptp_clock_request *rq, int on)
128 {
129 return -EOPNOTSUPP;
130 }
131
132 static struct ptp_clock_info rcar_gen4_ptp_info = {
133 .owner = THIS_MODULE,
134 .name = "rcar_gen4_ptp",
135 .max_adj = 50000000,
136 .adjfine = rcar_gen4_ptp_adjfine,
137 .adjtime = rcar_gen4_ptp_adjtime,
138 .gettime64 = rcar_gen4_ptp_gettime,
139 .settime64 = rcar_gen4_ptp_settime,
140 .enable = rcar_gen4_ptp_enable,
141 };
142
rcar_gen4_ptp_rate_to_increment(u32 rate)143 static s64 rcar_gen4_ptp_rate_to_increment(u32 rate)
144 {
145 /* Timer increment in ns.
146 * bit[31:27] - integer
147 * bit[26:0] - decimal
148 * increment[ns] = perid[ns] * 2^27 => (1ns * 2^27) / rate[hz]
149 */
150 return div_s64(1000000000LL << 27, rate);
151 }
152
rcar_gen4_ptp_register(struct rcar_gen4_ptp_private * ptp_priv,u32 rate)153 int rcar_gen4_ptp_register(struct rcar_gen4_ptp_private *ptp_priv, u32 rate)
154 {
155 if (ptp_priv->initialized)
156 return 0;
157
158 spin_lock_init(&ptp_priv->lock);
159
160 ptp_priv->default_addend = rcar_gen4_ptp_rate_to_increment(rate);
161 iowrite32(ptp_priv->default_addend, ptp_priv->addr + PTPTIVC0_REG);
162 ptp_priv->clock = ptp_clock_register(&ptp_priv->info, NULL);
163 if (IS_ERR(ptp_priv->clock))
164 return PTR_ERR(ptp_priv->clock);
165
166 iowrite32(0x01, ptp_priv->addr + PTPTMEC_REG);
167 ptp_priv->initialized = true;
168
169 return 0;
170 }
171 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_register);
172
rcar_gen4_ptp_unregister(struct rcar_gen4_ptp_private * ptp_priv)173 int rcar_gen4_ptp_unregister(struct rcar_gen4_ptp_private *ptp_priv)
174 {
175 iowrite32(1, ptp_priv->addr + PTPTMDC_REG);
176
177 return ptp_clock_unregister(ptp_priv->clock);
178 }
179 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_unregister);
180
rcar_gen4_ptp_alloc(struct platform_device * pdev,void __iomem * addr)181 struct rcar_gen4_ptp_private *rcar_gen4_ptp_alloc(struct platform_device *pdev,
182 void __iomem *addr)
183 {
184 struct rcar_gen4_ptp_private *ptp;
185
186 ptp = devm_kzalloc(&pdev->dev, sizeof(*ptp), GFP_KERNEL);
187 if (!ptp)
188 return NULL;
189
190 ptp->info = rcar_gen4_ptp_info;
191
192 ptp->addr = addr;
193
194 return ptp;
195 }
196 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_alloc);
197
rcar_gen4_ptp_clock_index(struct rcar_gen4_ptp_private * priv)198 int rcar_gen4_ptp_clock_index(struct rcar_gen4_ptp_private *priv)
199 {
200 if (!priv->initialized)
201 return -1;
202
203 return ptp_clock_index(priv->clock);
204 }
205 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_clock_index);
206
rcar_gen4_ptp_gettime64(struct rcar_gen4_ptp_private * priv,struct timespec64 * ts)207 void rcar_gen4_ptp_gettime64(struct rcar_gen4_ptp_private *priv,
208 struct timespec64 *ts)
209 {
210 if (!priv->initialized)
211 return;
212
213 priv->info.gettime64(&priv->info, ts);
214 }
215 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_gettime64);
216
217 MODULE_AUTHOR("Yoshihiro Shimoda");
218 MODULE_DESCRIPTION("Renesas R-Car Gen4 gPTP driver");
219 MODULE_LICENSE("GPL");
220