155714Skris/*
255714Skris * AMD 10Gb Ethernet driver
355714Skris *
455714Skris * This file is available to you under your choice of the following two
555714Skris * licenses:
655714Skris *
755714Skris * License 1: GPLv2
8280304Sjkim *
955714Skris * Copyright (c) 2014 Advanced Micro Devices, Inc.
1055714Skris *
1155714Skris * This file is free software; you may copy, redistribute and/or modify
1255714Skris * it under the terms of the GNU General Public License as published by
1355714Skris * the Free Software Foundation, either version 2 of the License, or (at
1455714Skris * your option) any later version.
15280304Sjkim *
1655714Skris * This file is distributed in the hope that it will be useful, but
1755714Skris * WITHOUT ANY WARRANTY; without even the implied warranty of
1855714Skris * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1955714Skris * General Public License for more details.
2055714Skris *
2155714Skris * You should have received a copy of the GNU General Public License
22280304Sjkim * along with this program.  If not, see <http://www.gnu.org/licenses/>.
2355714Skris *
2455714Skris * This file incorporates work covered by the following copyright and
2555714Skris * permission notice:
2655714Skris *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
2755714Skris *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
2855714Skris *     Inc. unless otherwise expressly agreed to in writing between Synopsys
2955714Skris *     and you.
3055714Skris *
3155714Skris *     The Software IS NOT an item of Licensed Software or Licensed Product
3255714Skris *     under any End User Software License Agreement or Agreement for Licensed
3355714Skris *     Product with Synopsys or any supplement thereto.  Permission is hereby
3455714Skris *     granted, free of charge, to any person obtaining a copy of this software
3555714Skris *     annotated with this license and the Software, to deal in the Software
3655714Skris *     without restriction, including without limitation the rights to use,
37280304Sjkim *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
3855714Skris *     of the Software, and to permit persons to whom the Software is furnished
3955714Skris *     to do so, subject to the following conditions:
40280304Sjkim *
4155714Skris *     The above copyright notice and this permission notice shall be included
4255714Skris *     in all copies or substantial portions of the Software.
4355714Skris *
4455714Skris *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
4555714Skris *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
4655714Skris *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
4755714Skris *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
4855714Skris *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
4955714Skris *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5055714Skris *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
5155714Skris *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
52280304Sjkim *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
5355714Skris *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
5455714Skris *     THE POSSIBILITY OF SUCH DAMAGE.
5555714Skris *
5655714Skris *
5755714Skris * License 2: Modified BSD
5855714Skris *
5955714Skris * Copyright (c) 2014 Advanced Micro Devices, Inc.
6055714Skris * All rights reserved.
6155714Skris *
6255714Skris * Redistribution and use in source and binary forms, with or without
6355714Skris * modification, are permitted provided that the following conditions are met:
6455714Skris *     * Redistributions of source code must retain the above copyright
6555714Skris *       notice, this list of conditions and the following disclaimer.
6655714Skris *     * Redistributions in binary form must reproduce the above copyright
67280304Sjkim *       notice, this list of conditions and the following disclaimer in the
6855714Skris *       documentation and/or other materials provided with the distribution.
69280304Sjkim *     * Neither the name of Advanced Micro Devices, Inc. nor the
7055714Skris *       names of its contributors may be used to endorse or promote products
7155714Skris *       derived from this software without specific prior written permission.
72280304Sjkim *
73280304Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
74280304Sjkim * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
75280304Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
76280304Sjkim * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
77280304Sjkim * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
78280304Sjkim * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
79280304Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
80280304Sjkim * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
81280304Sjkim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
82280304Sjkim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
8355714Skris *
84280304Sjkim * This file incorporates work covered by the following copyright and
85280304Sjkim * permission notice:
86280304Sjkim *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
87280304Sjkim *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
8855714Skris *     Inc. unless otherwise expressly agreed to in writing between Synopsys
89280304Sjkim *     and you.
90280304Sjkim *
91280304Sjkim *     The Software IS NOT an item of Licensed Software or Licensed Product
92280304Sjkim *     under any End User Software License Agreement or Agreement for Licensed
93280304Sjkim *     Product with Synopsys or any supplement thereto.  Permission is hereby
94280304Sjkim *     granted, free of charge, to any person obtaining a copy of this software
95280304Sjkim *     annotated with this license and the Software, to deal in the Software
96280304Sjkim *     without restriction, including without limitation the rights to use,
97280304Sjkim *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
98280304Sjkim *     of the Software, and to permit persons to whom the Software is furnished
99280304Sjkim *     to do so, subject to the following conditions:
100280304Sjkim *
101280304Sjkim *     The above copyright notice and this permission notice shall be included
102280304Sjkim *     in all copies or substantial portions of the Software.
103280304Sjkim *
10455714Skris *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
105280304Sjkim *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
106280304Sjkim *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
107280304Sjkim *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
108280304Sjkim *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
109280304Sjkim *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
110280304Sjkim *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
111280304Sjkim *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
112280304Sjkim *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
113280304Sjkim *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
114280304Sjkim *     THE POSSIBILITY OF SUCH DAMAGE.
115280304Sjkim */
116280304Sjkim#include <sys/cdefs.h>
117280304Sjkim#include "xgbe.h"
118280304Sjkim
119280304Sjkimstatic u64 xgbe_cc_read(const struct cyclecounter *cc)
120280304Sjkim{
121280304Sjkim	struct xgbe_prv_data *pdata = container_of(cc,
122280304Sjkim						   struct xgbe_prv_data,
123280304Sjkim						   tstamp_cc);
124280304Sjkim	u64 nsec;
125280304Sjkim
126280304Sjkim	nsec = pdata->hw_if.get_tstamp_time(pdata);
127280304Sjkim
128280304Sjkim	return (nsec);
129280304Sjkim}
130280304Sjkim
131280304Sjkimstatic int xgbe_adjfreq(struct ptp_clock_info *info, s32 delta)
132280304Sjkim{
133280304Sjkim	struct xgbe_prv_data *pdata = container_of(info,
134280304Sjkim						   struct xgbe_prv_data,
135280304Sjkim						   ptp_clock_info);
136280304Sjkim	unsigned long flags;
13755714Skris	u64 adjust;
138280304Sjkim	u32 addend, diff;
139280304Sjkim	unsigned int neg_adjust = 0;
140280304Sjkim
141280304Sjkim	if (delta < 0) {
142280304Sjkim		neg_adjust = 1;
143280304Sjkim		delta = -delta;
144280304Sjkim	}
145280304Sjkim
146280304Sjkim	adjust = pdata->tstamp_addend;
147280304Sjkim	adjust *= delta;
148280304Sjkim	diff = div_u64(adjust, 1000000000UL);
149280304Sjkim
150280304Sjkim	addend = (neg_adjust) ? pdata->tstamp_addend - diff :
151280304Sjkim				pdata->tstamp_addend + diff;
152280304Sjkim
153280304Sjkim	spin_lock_irqsave(&pdata->tstamp_lock, flags);
154280304Sjkim
155280304Sjkim	pdata->hw_if.update_tstamp_addend(pdata, addend);
156280304Sjkim
157280304Sjkim	spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
158280304Sjkim
159280304Sjkim	return (0);
160280304Sjkim}
161280304Sjkim
162280304Sjkimstatic int xgbe_adjtime(struct ptp_clock_info *info, s64 delta)
163280304Sjkim{
16455714Skris	struct xgbe_prv_data *pdata = container_of(info,
165280304Sjkim						   struct xgbe_prv_data,
166280304Sjkim						   ptp_clock_info);
167280304Sjkim	unsigned long flags;
168280304Sjkim
169280304Sjkim	spin_lock_irqsave(&pdata->tstamp_lock, flags);
170280304Sjkim	timecounter_adjtime(&pdata->tstamp_tc, delta);
171280304Sjkim	spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
172280304Sjkim
17355714Skris	return (0);
174280304Sjkim}
175280304Sjkim
176280304Sjkimstatic int xgbe_gettime(struct ptp_clock_info *info, struct timespec64 *ts)
177280304Sjkim{
178280304Sjkim	struct xgbe_prv_data *pdata = container_of(info,
179280304Sjkim						   struct xgbe_prv_data,
180280304Sjkim						   ptp_clock_info);
181280304Sjkim	unsigned long flags;
182109998Smarkm	u64 nsec;
183280304Sjkim
184280304Sjkim	spin_lock_irqsave(&pdata->tstamp_lock, flags);
18555714Skris
186280304Sjkim	nsec = timecounter_read(&pdata->tstamp_tc);
187280304Sjkim
188280304Sjkim	spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
189280304Sjkim
190280304Sjkim	*ts = ns_to_timespec64(nsec);
191280304Sjkim
192280304Sjkim	return (0);
193280304Sjkim}
194280304Sjkim
195280304Sjkimstatic int xgbe_settime(struct ptp_clock_info *info,
196280304Sjkim			const struct timespec64 *ts)
197280304Sjkim{
198280304Sjkim	struct xgbe_prv_data *pdata = container_of(info,
199280304Sjkim						   struct xgbe_prv_data,
20055714Skris						   ptp_clock_info);
201280304Sjkim	unsigned long flags;
202280304Sjkim	u64 nsec;
203280304Sjkim
204280304Sjkim	nsec = timespec64_to_ns(ts);
205280304Sjkim
20655714Skris	spin_lock_irqsave(&pdata->tstamp_lock, flags);
207280304Sjkim
208280304Sjkim	timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc, nsec);
209280304Sjkim
210280304Sjkim	spin_unlock_irqrestore(&pdata->tstamp_lock, flags);
211280304Sjkim
212280304Sjkim	return (0);
213280304Sjkim}
214280304Sjkim
215280304Sjkimstatic int xgbe_enable(struct ptp_clock_info *info,
216280304Sjkim    void *request, int on)
217280304Sjkim{
218280304Sjkim	return (-EOPNOTSUPP);
219280304Sjkim}
22055714Skris
221280304Sjkimvoid xgbe_ptp_register(struct xgbe_prv_data *pdata)
222280304Sjkim{
223280304Sjkim	struct ptp_clock_info *info = &pdata->ptp_clock_info;
224280304Sjkim	//struct ptp_clock *clock;
225280304Sjkim	struct cyclecounter *cc = &pdata->tstamp_cc;
226280304Sjkim	u64 dividend;
22755714Skris
228280304Sjkim	snprintf(info->name, sizeof(info->name), "axgbe-ptp");
229280304Sjkim	//info->owner = THIS_MODULE;
230280304Sjkim	info->max_adj = pdata->ptpclk_rate;
231280304Sjkim	info->adjfreq = xgbe_adjfreq;
232280304Sjkim	info->adjtime = xgbe_adjtime;
233280304Sjkim	info->gettime64 = xgbe_gettime;
234280304Sjkim	info->settime64 = xgbe_settime;
235280304Sjkim	info->enable = xgbe_enable;
236280304Sjkim#if 0
237280304Sjkim	clock = ptp_clock_register(info, pdata->dev);
238280304Sjkim	if (IS_ERR(clock)) {
239280304Sjkim		dev_err(pdata->dev, "ptp_clock_register failed\n");
240280304Sjkim		return;
241280304Sjkim	}
242280304Sjkim
243280304Sjkim	pdata->ptp_clock = clock;
244280304Sjkim#endif
245280304Sjkim	/* Calculate the addend:
246280304Sjkim	 *   addend = 2^32 / (PTP ref clock / 50Mhz)
247280304Sjkim	 *          = (2^32 * 50Mhz) / PTP ref clock
248280304Sjkim	 */
249280304Sjkim	dividend = 50000000;
250280304Sjkim	dividend <<= 32;
251280304Sjkim	pdata->tstamp_addend = div_u64(dividend, pdata->ptpclk_rate);
252280304Sjkim
253280304Sjkim	/* Setup the timecounter */
254280304Sjkim	cc->read = xgbe_cc_read;
255280304Sjkim	cc->mask = CLOCKSOURCE_MASK(64);
25655714Skris	cc->mult = 1;
25755714Skris	cc->shift = 0;
258280304Sjkim
259280304Sjkim	timecounter_init(&pdata->tstamp_tc, &pdata->tstamp_cc,
260280304Sjkim			 ktime_to_ns(ktime_get_real()));
261280304Sjkim
262280304Sjkim	/* Disable all timestamping to start */
26355714Skris	XGMAC_IOWRITE(pdata, MAC_TSCR, 0);
264280304Sjkim	pdata->tstamp_config.tx_type = HWTSTAMP_TX_OFF;
265280304Sjkim	pdata->tstamp_config.rx_filter = HWTSTAMP_FILTER_NONE;
266280304Sjkim}
267280304Sjkim
268280304Sjkimvoid xgbe_ptp_unregister(struct xgbe_prv_data *pdata)
269280304Sjkim{
27055714Skris#if 0
271280304Sjkim	if (pdata->ptp_clock)
272280304Sjkim		ptp_clock_unregister(pdata->ptp_clock);
273280304Sjkim#endif
274280304Sjkim}
275280304Sjkim