1 | /* |
2 | * AMD 10Gb Ethernet driver |
3 | * |
4 | * This file is available to you under your choice of the following two |
5 | * licenses: |
6 | * |
7 | * License 1: GPLv2 |
8 | * |
9 | * Copyright (c) 2014 Advanced Micro Devices, Inc. |
10 | * |
11 | * This file is free software; you may copy, redistribute and/or modify |
12 | * it under the terms of the GNU General Public License as published by |
13 | * the Free Software Foundation, either version 2 of the License, or (at |
14 | * your option) any later version. |
15 | * |
16 | * This file is distributed in the hope that it will be useful, but |
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
19 | * General Public License for more details. |
20 | * |
21 | * You should have received a copy of the GNU General Public License |
22 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
23 | * |
24 | * This file incorporates work covered by the following copyright and |
25 | * permission notice: |
26 | * The Synopsys DWC ETHER XGMAC Software Driver and documentation |
27 | * (hereinafter "Software") is an unsupported proprietary work of Synopsys, |
28 | * Inc. unless otherwise expressly agreed to in writing between Synopsys |
29 | * and you. |
30 | * |
31 | * The Software IS NOT an item of Licensed Software or Licensed Product |
32 | * under any End User Software License Agreement or Agreement for Licensed |
33 | * Product with Synopsys or any supplement thereto. Permission is hereby |
34 | * granted, free of charge, to any person obtaining a copy of this software |
35 | * annotated with this license and the Software, to deal in the Software |
36 | * without restriction, including without limitation the rights to use, |
37 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
38 | * of the Software, and to permit persons to whom the Software is furnished |
39 | * to do so, subject to the following conditions: |
40 | * |
41 | * The above copyright notice and this permission notice shall be included |
42 | * in all copies or substantial portions of the Software. |
43 | * |
44 | * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" |
45 | * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
46 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
47 | * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS |
48 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
49 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
50 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
51 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
52 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
53 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
54 | * THE POSSIBILITY OF SUCH DAMAGE. |
55 | * |
56 | * |
57 | * License 2: Modified BSD |
58 | * |
59 | * Copyright (c) 2014 Advanced Micro Devices, Inc. |
60 | * All rights reserved. |
61 | * |
62 | * Redistribution and use in source and binary forms, with or without |
63 | * modification, are permitted provided that the following conditions are met: |
64 | * * Redistributions of source code must retain the above copyright |
65 | * notice, this list of conditions and the following disclaimer. |
66 | * * Redistributions in binary form must reproduce the above copyright |
67 | * notice, this list of conditions and the following disclaimer in the |
68 | * documentation and/or other materials provided with the distribution. |
69 | * * Neither the name of Advanced Micro Devices, Inc. nor the |
70 | * names of its contributors may be used to endorse or promote products |
71 | * derived from this software without specific prior written permission. |
72 | * |
73 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
74 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
75 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
76 | * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY |
77 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
78 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
79 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
80 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
81 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
82 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
83 | * |
84 | * This file incorporates work covered by the following copyright and |
85 | * permission notice: |
86 | * The Synopsys DWC ETHER XGMAC Software Driver and documentation |
87 | * (hereinafter "Software") is an unsupported proprietary work of Synopsys, |
88 | * Inc. unless otherwise expressly agreed to in writing between Synopsys |
89 | * and you. |
90 | * |
91 | * The Software IS NOT an item of Licensed Software or Licensed Product |
92 | * under any End User Software License Agreement or Agreement for Licensed |
93 | * Product with Synopsys or any supplement thereto. Permission is hereby |
94 | * granted, free of charge, to any person obtaining a copy of this software |
95 | * annotated with this license and the Software, to deal in the Software |
96 | * without restriction, including without limitation the rights to use, |
97 | * copy, modify, merge, publish, distribute, sublicense, and/or sell copies |
98 | * of the Software, and to permit persons to whom the Software is furnished |
99 | * to do so, subject to the following conditions: |
100 | * |
101 | * The above copyright notice and this permission notice shall be included |
102 | * in all copies or substantial portions of the Software. |
103 | * |
104 | * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" |
105 | * BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
106 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
107 | * PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS |
108 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
109 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
110 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
111 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
112 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
113 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
114 | * THE POSSIBILITY OF SUCH DAMAGE. |
115 | */ |
116 | |
117 | #include <linux/clk.h> |
118 | #include <linux/clocksource.h> |
119 | #include <linux/ptp_clock_kernel.h> |
120 | #include <linux/net_tstamp.h> |
121 | |
122 | #include "xgbe.h" |
123 | #include "xgbe-common.h" |
124 | |
125 | static u64 xgbe_cc_read(const struct cyclecounter *cc) |
126 | { |
127 | struct xgbe_prv_data *pdata = container_of(cc, |
128 | struct xgbe_prv_data, |
129 | tstamp_cc); |
130 | u64 nsec; |
131 | |
132 | nsec = pdata->hw_if.get_tstamp_time(pdata); |
133 | |
134 | return nsec; |
135 | } |
136 | |
137 | static int xgbe_adjfine(struct ptp_clock_info *info, long scaled_ppm) |
138 | { |
139 | struct xgbe_prv_data *pdata = container_of(info, |
140 | struct xgbe_prv_data, |
141 | ptp_clock_info); |
142 | unsigned long flags; |
143 | u64 addend; |
144 | |
145 | addend = adjust_by_scaled_ppm(base: pdata->tstamp_addend, scaled_ppm); |
146 | |
147 | spin_lock_irqsave(&pdata->tstamp_lock, flags); |
148 | |
149 | pdata->hw_if.update_tstamp_addend(pdata, addend); |
150 | |
151 | spin_unlock_irqrestore(lock: &pdata->tstamp_lock, flags); |
152 | |
153 | return 0; |
154 | } |
155 | |
156 | static int xgbe_adjtime(struct ptp_clock_info *info, s64 delta) |
157 | { |
158 | struct xgbe_prv_data *pdata = container_of(info, |
159 | struct xgbe_prv_data, |
160 | ptp_clock_info); |
161 | unsigned long flags; |
162 | |
163 | spin_lock_irqsave(&pdata->tstamp_lock, flags); |
164 | timecounter_adjtime(tc: &pdata->tstamp_tc, delta); |
165 | spin_unlock_irqrestore(lock: &pdata->tstamp_lock, flags); |
166 | |
167 | return 0; |
168 | } |
169 | |
170 | static int xgbe_gettime(struct ptp_clock_info *info, struct timespec64 *ts) |
171 | { |
172 | struct xgbe_prv_data *pdata = container_of(info, |
173 | struct xgbe_prv_data, |
174 | ptp_clock_info); |
175 | unsigned long flags; |
176 | u64 nsec; |
177 | |
178 | spin_lock_irqsave(&pdata->tstamp_lock, flags); |
179 | |
180 | nsec = timecounter_read(tc: &pdata->tstamp_tc); |
181 | |
182 | spin_unlock_irqrestore(lock: &pdata->tstamp_lock, flags); |
183 | |
184 | *ts = ns_to_timespec64(nsec); |
185 | |
186 | return 0; |
187 | } |
188 | |
189 | static int xgbe_settime(struct ptp_clock_info *info, |
190 | const struct timespec64 *ts) |
191 | { |
192 | struct xgbe_prv_data *pdata = container_of(info, |
193 | struct xgbe_prv_data, |
194 | ptp_clock_info); |
195 | unsigned long flags; |
196 | u64 nsec; |
197 | |
198 | nsec = timespec64_to_ns(ts); |
199 | |
200 | spin_lock_irqsave(&pdata->tstamp_lock, flags); |
201 | |
202 | timecounter_init(tc: &pdata->tstamp_tc, cc: &pdata->tstamp_cc, start_tstamp: nsec); |
203 | |
204 | spin_unlock_irqrestore(lock: &pdata->tstamp_lock, flags); |
205 | |
206 | return 0; |
207 | } |
208 | |
209 | static int xgbe_enable(struct ptp_clock_info *info, |
210 | struct ptp_clock_request *request, int on) |
211 | { |
212 | return -EOPNOTSUPP; |
213 | } |
214 | |
215 | void xgbe_ptp_register(struct xgbe_prv_data *pdata) |
216 | { |
217 | struct ptp_clock_info *info = &pdata->ptp_clock_info; |
218 | struct ptp_clock *clock; |
219 | struct cyclecounter *cc = &pdata->tstamp_cc; |
220 | u64 dividend; |
221 | |
222 | snprintf(buf: info->name, size: sizeof(info->name), fmt: "%s" , |
223 | netdev_name(dev: pdata->netdev)); |
224 | info->owner = THIS_MODULE; |
225 | info->max_adj = pdata->ptpclk_rate; |
226 | info->adjfine = xgbe_adjfine; |
227 | info->adjtime = xgbe_adjtime; |
228 | info->gettime64 = xgbe_gettime; |
229 | info->settime64 = xgbe_settime; |
230 | info->enable = xgbe_enable; |
231 | |
232 | clock = ptp_clock_register(info, parent: pdata->dev); |
233 | if (IS_ERR(ptr: clock)) { |
234 | dev_err(pdata->dev, "ptp_clock_register failed\n" ); |
235 | return; |
236 | } |
237 | |
238 | pdata->ptp_clock = clock; |
239 | |
240 | /* Calculate the addend: |
241 | * addend = 2^32 / (PTP ref clock / 50Mhz) |
242 | * = (2^32 * 50Mhz) / PTP ref clock |
243 | */ |
244 | dividend = 50000000; |
245 | dividend <<= 32; |
246 | pdata->tstamp_addend = div_u64(dividend, divisor: pdata->ptpclk_rate); |
247 | |
248 | /* Setup the timecounter */ |
249 | cc->read = xgbe_cc_read; |
250 | cc->mask = CLOCKSOURCE_MASK(64); |
251 | cc->mult = 1; |
252 | cc->shift = 0; |
253 | |
254 | timecounter_init(tc: &pdata->tstamp_tc, cc: &pdata->tstamp_cc, |
255 | start_tstamp: ktime_to_ns(kt: ktime_get_real())); |
256 | |
257 | /* Disable all timestamping to start */ |
258 | XGMAC_IOWRITE(pdata, MAC_TSCR, 0); |
259 | pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF; |
260 | pdata->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE; |
261 | } |
262 | |
263 | void xgbe_ptp_unregister(struct xgbe_prv_data *pdata) |
264 | { |
265 | if (pdata->ptp_clock) |
266 | ptp_clock_unregister(ptp: pdata->ptp_clock); |
267 | } |
268 | |