xref: /linux/drivers/net/ethernet/renesas/rcar_gen4_ptp.c (revision ccde82e909467abdf098a8ee6f63e1ecf9a47ce5)
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/slab.h>
13 
14 #include "rcar_gen4_ptp.h"
15 
16 #define PTPTMEC_REG		0x0010
17 #define PTPTMDC_REG		0x0014
18 #define PTPTIVC0_REG		0x0020
19 #define PTPTOVC00_REG		0x0030
20 #define PTPTOVC10_REG		0x0034
21 #define PTPTOVC20_REG		0x0038
22 #define PTPGPTPTM00_REG		0x0050
23 #define PTPGPTPTM10_REG		0x0054
24 #define PTPGPTPTM20_REG		0x0058
25 
26 #define ptp_to_priv(ptp)	container_of(ptp, struct rcar_gen4_ptp_private, info)
27 
28 static int rcar_gen4_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
29 {
30 	struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
31 	s64 addend = ptp_priv->default_addend;
32 	bool neg_adj = scaled_ppm < 0;
33 	s64 diff;
34 
35 	if (neg_adj)
36 		scaled_ppm = -scaled_ppm;
37 	diff = div_s64(addend * scaled_ppm_to_ppb(scaled_ppm), NSEC_PER_SEC);
38 	addend = neg_adj ? addend - diff : addend + diff;
39 
40 	iowrite32(addend, ptp_priv->addr + PTPTIVC0_REG);
41 
42 	return 0;
43 }
44 
45 static void _rcar_gen4_ptp_gettime(struct ptp_clock_info *ptp,
46 				   struct timespec64 *ts)
47 {
48 	struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
49 
50 	lockdep_assert_held(&ptp_priv->lock);
51 
52 	ts->tv_nsec = ioread32(ptp_priv->addr + PTPGPTPTM00_REG);
53 	ts->tv_sec = ioread32(ptp_priv->addr + PTPGPTPTM10_REG) |
54 		     ((s64)ioread32(ptp_priv->addr + PTPGPTPTM20_REG) << 32);
55 }
56 
57 static int rcar_gen4_ptp_gettime(struct ptp_clock_info *ptp,
58 				 struct timespec64 *ts)
59 {
60 	struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
61 	unsigned long flags;
62 
63 	spin_lock_irqsave(&ptp_priv->lock, flags);
64 	_rcar_gen4_ptp_gettime(ptp, ts);
65 	spin_unlock_irqrestore(&ptp_priv->lock, flags);
66 
67 	return 0;
68 }
69 
70 /* Caller must hold the lock */
71 static void _rcar_gen4_ptp_settime(struct ptp_clock_info *ptp,
72 				   const struct timespec64 *ts)
73 {
74 	struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
75 
76 	iowrite32(1, ptp_priv->addr + PTPTMDC_REG);
77 	iowrite32(0, ptp_priv->addr + PTPTOVC20_REG);
78 	iowrite32(0, ptp_priv->addr + PTPTOVC10_REG);
79 	iowrite32(0, ptp_priv->addr + PTPTOVC00_REG);
80 	iowrite32(1, ptp_priv->addr + PTPTMEC_REG);
81 	iowrite32(ts->tv_sec >> 32, ptp_priv->addr + PTPTOVC20_REG);
82 	iowrite32(ts->tv_sec, ptp_priv->addr + PTPTOVC10_REG);
83 	iowrite32(ts->tv_nsec, ptp_priv->addr + PTPTOVC00_REG);
84 }
85 
86 static int rcar_gen4_ptp_settime(struct ptp_clock_info *ptp,
87 				 const struct timespec64 *ts)
88 {
89 	struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
90 	unsigned long flags;
91 
92 	spin_lock_irqsave(&ptp_priv->lock, flags);
93 	_rcar_gen4_ptp_settime(ptp, ts);
94 	spin_unlock_irqrestore(&ptp_priv->lock, flags);
95 
96 	return 0;
97 }
98 
99 static int rcar_gen4_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
100 {
101 	struct rcar_gen4_ptp_private *ptp_priv = ptp_to_priv(ptp);
102 	struct timespec64 ts;
103 	unsigned long flags;
104 	s64 now;
105 
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);
112 
113 	return 0;
114 }
115 
116 static int rcar_gen4_ptp_enable(struct ptp_clock_info *ptp,
117 				struct ptp_clock_request *rq, int on)
118 {
119 	return -EOPNOTSUPP;
120 }
121 
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,
131 };
132 
133 static s64 rcar_gen4_ptp_rate_to_increment(u32 rate)
134 {
135 	/* Timer increment in ns.
136 	 * bit[31:27] - integer
137 	 * bit[26:0]  - decimal
138 	 * increment[ns] = perid[ns] * 2^27 => (1ns * 2^27) / rate[hz]
139 	 */
140 	return div_s64(1000000000LL << 27, rate);
141 }
142 
143 int rcar_gen4_ptp_register(struct rcar_gen4_ptp_private *ptp_priv, u32 rate)
144 {
145 	if (ptp_priv->initialized)
146 		return 0;
147 
148 	spin_lock_init(&ptp_priv->lock);
149 
150 	ptp_priv->default_addend = rcar_gen4_ptp_rate_to_increment(rate);
151 	iowrite32(ptp_priv->default_addend, ptp_priv->addr + PTPTIVC0_REG);
152 	ptp_priv->clock = ptp_clock_register(&ptp_priv->info, NULL);
153 	if (IS_ERR(ptp_priv->clock))
154 		return PTR_ERR(ptp_priv->clock);
155 
156 	iowrite32(0x01, ptp_priv->addr + PTPTMEC_REG);
157 	ptp_priv->initialized = true;
158 
159 	return 0;
160 }
161 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_register);
162 
163 int rcar_gen4_ptp_unregister(struct rcar_gen4_ptp_private *ptp_priv)
164 {
165 	iowrite32(1, ptp_priv->addr + PTPTMDC_REG);
166 
167 	return ptp_clock_unregister(ptp_priv->clock);
168 }
169 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_unregister);
170 
171 struct rcar_gen4_ptp_private *rcar_gen4_ptp_alloc(struct platform_device *pdev)
172 {
173 	struct rcar_gen4_ptp_private *ptp;
174 
175 	ptp = devm_kzalloc(&pdev->dev, sizeof(*ptp), GFP_KERNEL);
176 	if (!ptp)
177 		return NULL;
178 
179 	ptp->info = rcar_gen4_ptp_info;
180 
181 	return ptp;
182 }
183 EXPORT_SYMBOL_GPL(rcar_gen4_ptp_alloc);
184 
185 MODULE_AUTHOR("Yoshihiro Shimoda");
186 MODULE_DESCRIPTION("Renesas R-Car Gen4 gPTP driver");
187 MODULE_LICENSE("GPL");
188