Merge tag 'trace-printf-v6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/trace...
[drm/drm-misc.git] / drivers / net / ethernet / renesas / rcar_gen4_ptp.c
blob72e7fcc56693a2a1f6ff675aa82614beb4501414
1 // SPDX-License-Identifier: GPL-2.0
2 /* Renesas R-Car Gen4 gPTP device driver
4 * Copyright (C) 2022 Renesas Electronics Corporation
5 */
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/slab.h>
14 #include "rcar_gen4_ptp.h"
15 #define ptp_to_priv(ptp) container_of(ptp, struct rcar_gen4_ptp_private, info)
17 static const struct rcar_gen4_ptp_reg_offset gen4_offs = {
18 .enable = PTPTMEC,
19 .disable = PTPTMDC,
20 .increment = PTPTIVC0,
21 .config_t0 = PTPTOVC00,
22 .config_t1 = PTPTOVC10,
23 .config_t2 = PTPTOVC20,
24 .monitor_t0 = PTPGPTPTM00,
25 .monitor_t1 = PTPGPTPTM10,
26 .monitor_t2 = PTPGPTPTM20,
29 static int rcar_gen4_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
31 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
32 bool neg_adj = scaled_ppm < 0 ? true : false;
33 s64 addend = ptp_priv->default_addend;
34 s64 diff;
36 if (neg_adj)
37 scaled_ppm = -scaled_ppm;
38 diff = div_s64(addend * scaled_ppm_to_ppb(scaled_ppm), NSEC_PER_SEC);
39 addend = neg_adj ? addend - diff : addend + diff;
41 iowrite32(addend, ptp_priv->addr + ptp_priv->offs->increment);
43 return 0;
46 /* Caller must hold the lock */
47 static void _rcar_gen4_ptp_gettime(struct ptp_clock_info *ptp,
48 struct timespec64 *ts)
50 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
52 ts->tv_nsec = ioread32(ptp_priv->addr + ptp_priv->offs->monitor_t0);
53 ts->tv_sec = ioread32(ptp_priv->addr + ptp_priv->offs->monitor_t1) |
54 ((s64)ioread32(ptp_priv->addr + ptp_priv->offs->monitor_t2) << 32);
57 static int rcar_gen4_ptp_gettime(struct ptp_clock_info *ptp,
58 struct timespec64 *ts)
60 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
61 unsigned long flags;
63 spin_lock_irqsave(&ptp_priv->lock, flags);
64 _rcar_gen4_ptp_gettime(ptp, ts);
65 spin_unlock_irqrestore(&ptp_priv->lock, flags);
67 return 0;
70 /* Caller must hold the lock */
71 static void _rcar_gen4_ptp_settime(struct ptp_clock_info *ptp,
72 const struct timespec64 *ts)
74 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
76 iowrite32(1, ptp_priv->addr + ptp_priv->offs->disable);
77 iowrite32(0, ptp_priv->addr + ptp_priv->offs->config_t2);
78 iowrite32(0, ptp_priv->addr + ptp_priv->offs->config_t1);
79 iowrite32(0, ptp_priv->addr + ptp_priv->offs->config_t0);
80 iowrite32(1, ptp_priv->addr + ptp_priv->offs->enable);
81 iowrite32(ts->tv_sec >> 32, ptp_priv->addr + ptp_priv->offs->config_t2);
82 iowrite32(ts->tv_sec, ptp_priv->addr + ptp_priv->offs->config_t1);
83 iowrite32(ts->tv_nsec, ptp_priv->addr + ptp_priv->offs->config_t0);
86 static int rcar_gen4_ptp_settime(struct ptp_clock_info *ptp,
87 const struct timespec64 *ts)
89 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
90 unsigned long flags;
92 spin_lock_irqsave(&ptp_priv->lock, flags);
93 _rcar_gen4_ptp_settime(ptp, ts);
94 spin_unlock_irqrestore(&ptp_priv->lock, flags);
96 return 0;
99 static int rcar_gen4_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
101 struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
102 struct timespec64 ts;
103 unsigned long flags;
104 s64 now;
106 spin_lock_irqsave(&ptp_priv->lock, flags);
107 _rcar_gen4_ptp_gettime(ptp, &ts);
108 now = ktime_to_ns(timespec64_to_ktime(ts));
109 ts = ns_to_timespec64(now + delta);
110 _rcar_gen4_ptp_settime(ptp, &ts);
111 spin_unlock_irqrestore(&ptp_priv->lock, flags);
113 return 0;
116 static int rcar_gen4_ptp_enable(struct ptp_clock_info *ptp,
117 struct ptp_clock_request *rq, int on)
119 return -EOPNOTSUPP;
122 static struct ptp_clock_info rcar_gen4_ptp_info = {
123 .owner = THIS_MODULE,
124 .name = "rcar_gen4_ptp",
125 .max_adj = 50000000,
126 .adjfine = rcar_gen4_ptp_adjfine,
127 .adjtime = rcar_gen4_ptp_adjtime,
128 .gettime64 = rcar_gen4_ptp_gettime,
129 .settime64 = rcar_gen4_ptp_settime,
130 .enable = rcar_gen4_ptp_enable,
133 static int rcar_gen4_ptp_set_offs(struct rcar_gen4_ptp_private *ptp_priv,
134 enum rcar_gen4_ptp_reg_layout layout)
136 if (layout != RCAR_GEN4_PTP_REG_LAYOUT)
137 return -EINVAL;
139 ptp_priv->offs = &gen4_offs;
141 return 0;
144 static s64 rcar_gen4_ptp_rate_to_increment(u32 rate)
146 /* Timer increment in ns.
147 * bit[31:27] - integer
148 * bit[26:0] - decimal
149 * increment[ns] = perid[ns] * 2^27 => (1ns * 2^27) / rate[hz]
151 return div_s64(1000000000LL << 27, rate);
154 int rcar_gen4_ptp_register(struct rcar_gen4_ptp_private *ptp_priv,
155 enum rcar_gen4_ptp_reg_layout layout, u32 rate)
157 int ret;
159 if (ptp_priv->initialized)
160 return 0;
162 spin_lock_init(&ptp_priv->lock);
164 ret = rcar_gen4_ptp_set_offs(ptp_priv, layout);
165 if (ret)
166 return ret;
168 ptp_priv->default_addend = rcar_gen4_ptp_rate_to_increment(rate);
169 iowrite32(ptp_priv->default_addend, ptp_priv->addr + ptp_priv->offs->increment);
170 ptp_priv->clock = ptp_clock_register(&ptp_priv->info, NULL);
171 if (IS_ERR(ptp_priv->clock))
172 return PTR_ERR(ptp_priv->clock);
174 iowrite32(0x01, ptp_priv->addr + ptp_priv->offs->enable);
175 ptp_priv->initialized = true;
177 return 0;
179 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_register);
181 int rcar_gen4_ptp_unregister(struct rcar_gen4_ptp_private *ptp_priv)
183 iowrite32(1, ptp_priv->addr + ptp_priv->offs->disable);
185 return ptp_clock_unregister(ptp_priv->clock);
187 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_unregister);
189 struct rcar_gen4_ptp_private *rcar_gen4_ptp_alloc(struct platform_device *pdev)
191 struct rcar_gen4_ptp_private *ptp;
193 ptp = devm_kzalloc(&pdev->dev, sizeof(*ptp), GFP_KERNEL);
194 if (!ptp)
195 return NULL;
197 ptp->info = rcar_gen4_ptp_info;
199 return ptp;
201 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_alloc);
203 MODULE_AUTHOR("Yoshihiro Shimoda");
204 MODULE_DESCRIPTION("Renesas R-Car Gen4 gPTP driver");
205 MODULE_LICENSE("GPL");