xref: /OK3568_Linux_fs/kernel/drivers/ptp/ptp_dte.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright 2017 Broadcom
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or
5*4882a593Smuzhiyun  * modify it under the terms of the GNU General Public License as
6*4882a593Smuzhiyun  * published by the Free Software Foundation version 2.
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
9*4882a593Smuzhiyun  * kind, whether express or implied; without even the implied warranty
10*4882a593Smuzhiyun  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11*4882a593Smuzhiyun  * GNU General Public License for more details.
12*4882a593Smuzhiyun  */
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include <linux/err.h>
15*4882a593Smuzhiyun #include <linux/io.h>
16*4882a593Smuzhiyun #include <linux/module.h>
17*4882a593Smuzhiyun #include <linux/mod_devicetable.h>
18*4882a593Smuzhiyun #include <linux/platform_device.h>
19*4882a593Smuzhiyun #include <linux/ptp_clock_kernel.h>
20*4882a593Smuzhiyun #include <linux/types.h>
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun #define DTE_NCO_LOW_TIME_REG	0x00
23*4882a593Smuzhiyun #define DTE_NCO_TIME_REG	0x04
24*4882a593Smuzhiyun #define DTE_NCO_OVERFLOW_REG	0x08
25*4882a593Smuzhiyun #define DTE_NCO_INC_REG		0x0c
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #define DTE_NCO_SUM2_MASK	0xffffffff
28*4882a593Smuzhiyun #define DTE_NCO_SUM2_SHIFT	4ULL
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #define DTE_NCO_SUM3_MASK	0xff
31*4882a593Smuzhiyun #define DTE_NCO_SUM3_SHIFT	36ULL
32*4882a593Smuzhiyun #define DTE_NCO_SUM3_WR_SHIFT	8
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define DTE_NCO_TS_WRAP_MASK	0xfff
35*4882a593Smuzhiyun #define DTE_NCO_TS_WRAP_LSHIFT	32
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #define DTE_NCO_INC_DEFAULT	0x80000000
38*4882a593Smuzhiyun #define DTE_NUM_REGS_TO_RESTORE	4
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun /* Full wrap around is 44bits in ns (~4.887 hrs) */
41*4882a593Smuzhiyun #define DTE_WRAP_AROUND_NSEC_SHIFT 44
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun /* 44 bits NCO */
44*4882a593Smuzhiyun #define DTE_NCO_MAX_NS	0xFFFFFFFFFFFLL
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun /* 125MHz with 3.29 reg cfg */
47*4882a593Smuzhiyun #define DTE_PPB_ADJ(ppb) (u32)(div64_u64((((u64)abs(ppb) * BIT(28)) +\
48*4882a593Smuzhiyun 				      62500000ULL), 125000000ULL))
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun /* ptp dte priv structure */
51*4882a593Smuzhiyun struct ptp_dte {
52*4882a593Smuzhiyun 	void __iomem *regs;
53*4882a593Smuzhiyun 	struct ptp_clock *ptp_clk;
54*4882a593Smuzhiyun 	struct ptp_clock_info caps;
55*4882a593Smuzhiyun 	struct device *dev;
56*4882a593Smuzhiyun 	u32 ts_ovf_last;
57*4882a593Smuzhiyun 	u32 ts_wrap_cnt;
58*4882a593Smuzhiyun 	spinlock_t lock;
59*4882a593Smuzhiyun 	u32 reg_val[DTE_NUM_REGS_TO_RESTORE];
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun 
dte_write_nco(void __iomem * regs,s64 ns)62*4882a593Smuzhiyun static void dte_write_nco(void __iomem *regs, s64 ns)
63*4882a593Smuzhiyun {
64*4882a593Smuzhiyun 	u32 sum2, sum3;
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun 	sum2 = (u32)((ns >> DTE_NCO_SUM2_SHIFT) & DTE_NCO_SUM2_MASK);
67*4882a593Smuzhiyun 	/* compensate for ignoring sum1 */
68*4882a593Smuzhiyun 	if (sum2 != DTE_NCO_SUM2_MASK)
69*4882a593Smuzhiyun 		sum2++;
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 	/* to write sum3, bits [15:8] needs to be written */
72*4882a593Smuzhiyun 	sum3 = (u32)(((ns >> DTE_NCO_SUM3_SHIFT) & DTE_NCO_SUM3_MASK) <<
73*4882a593Smuzhiyun 		     DTE_NCO_SUM3_WR_SHIFT);
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	writel(0, (regs + DTE_NCO_LOW_TIME_REG));
76*4882a593Smuzhiyun 	writel(sum2, (regs + DTE_NCO_TIME_REG));
77*4882a593Smuzhiyun 	writel(sum3, (regs + DTE_NCO_OVERFLOW_REG));
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun 
dte_read_nco(void __iomem * regs)80*4882a593Smuzhiyun static s64 dte_read_nco(void __iomem *regs)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun 	u32 sum2, sum3;
83*4882a593Smuzhiyun 	s64 ns;
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	/*
86*4882a593Smuzhiyun 	 * ignoring sum1 (4 bits) gives a 16ns resolution, which
87*4882a593Smuzhiyun 	 * works due to the async register read.
88*4882a593Smuzhiyun 	 */
89*4882a593Smuzhiyun 	sum3 = readl(regs + DTE_NCO_OVERFLOW_REG) & DTE_NCO_SUM3_MASK;
90*4882a593Smuzhiyun 	sum2 = readl(regs + DTE_NCO_TIME_REG);
91*4882a593Smuzhiyun 	ns = ((s64)sum3 << DTE_NCO_SUM3_SHIFT) |
92*4882a593Smuzhiyun 		 ((s64)sum2 << DTE_NCO_SUM2_SHIFT);
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	return ns;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
dte_write_nco_delta(struct ptp_dte * ptp_dte,s64 delta)97*4882a593Smuzhiyun static void dte_write_nco_delta(struct ptp_dte *ptp_dte, s64 delta)
98*4882a593Smuzhiyun {
99*4882a593Smuzhiyun 	s64 ns;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	ns = dte_read_nco(ptp_dte->regs);
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	/* handle wraparound conditions */
104*4882a593Smuzhiyun 	if ((delta < 0) && (abs(delta) > ns)) {
105*4882a593Smuzhiyun 		if (ptp_dte->ts_wrap_cnt) {
106*4882a593Smuzhiyun 			ns += DTE_NCO_MAX_NS + delta;
107*4882a593Smuzhiyun 			ptp_dte->ts_wrap_cnt--;
108*4882a593Smuzhiyun 		} else {
109*4882a593Smuzhiyun 			ns = 0;
110*4882a593Smuzhiyun 		}
111*4882a593Smuzhiyun 	} else {
112*4882a593Smuzhiyun 		ns += delta;
113*4882a593Smuzhiyun 		if (ns > DTE_NCO_MAX_NS) {
114*4882a593Smuzhiyun 			ptp_dte->ts_wrap_cnt++;
115*4882a593Smuzhiyun 			ns -= DTE_NCO_MAX_NS;
116*4882a593Smuzhiyun 		}
117*4882a593Smuzhiyun 	}
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun 	dte_write_nco(ptp_dte->regs, ns);
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	ptp_dte->ts_ovf_last = (ns >> DTE_NCO_TS_WRAP_LSHIFT) &
122*4882a593Smuzhiyun 			DTE_NCO_TS_WRAP_MASK;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
dte_read_nco_with_ovf(struct ptp_dte * ptp_dte)125*4882a593Smuzhiyun static s64 dte_read_nco_with_ovf(struct ptp_dte *ptp_dte)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	u32 ts_ovf;
128*4882a593Smuzhiyun 	s64 ns = 0;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	ns = dte_read_nco(ptp_dte->regs);
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	/*Timestamp overflow: 8 LSB bits of sum3, 4 MSB bits of sum2 */
133*4882a593Smuzhiyun 	ts_ovf = (ns >> DTE_NCO_TS_WRAP_LSHIFT) & DTE_NCO_TS_WRAP_MASK;
134*4882a593Smuzhiyun 
135*4882a593Smuzhiyun 	/* Check for wrap around */
136*4882a593Smuzhiyun 	if (ts_ovf < ptp_dte->ts_ovf_last)
137*4882a593Smuzhiyun 		ptp_dte->ts_wrap_cnt++;
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	ptp_dte->ts_ovf_last = ts_ovf;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	/* adjust for wraparounds */
142*4882a593Smuzhiyun 	ns += (s64)(BIT_ULL(DTE_WRAP_AROUND_NSEC_SHIFT) * ptp_dte->ts_wrap_cnt);
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	return ns;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
ptp_dte_adjfreq(struct ptp_clock_info * ptp,s32 ppb)147*4882a593Smuzhiyun static int ptp_dte_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun 	u32 nco_incr;
150*4882a593Smuzhiyun 	unsigned long flags;
151*4882a593Smuzhiyun 	struct ptp_dte *ptp_dte = container_of(ptp, struct ptp_dte, caps);
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	if (abs(ppb) > ptp_dte->caps.max_adj) {
154*4882a593Smuzhiyun 		dev_err(ptp_dte->dev, "ppb adj too big\n");
155*4882a593Smuzhiyun 		return -EINVAL;
156*4882a593Smuzhiyun 	}
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	if (ppb < 0)
159*4882a593Smuzhiyun 		nco_incr = DTE_NCO_INC_DEFAULT - DTE_PPB_ADJ(ppb);
160*4882a593Smuzhiyun 	else
161*4882a593Smuzhiyun 		nco_incr = DTE_NCO_INC_DEFAULT + DTE_PPB_ADJ(ppb);
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	spin_lock_irqsave(&ptp_dte->lock, flags);
164*4882a593Smuzhiyun 	writel(nco_incr, ptp_dte->regs + DTE_NCO_INC_REG);
165*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ptp_dte->lock, flags);
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	return 0;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun 
ptp_dte_adjtime(struct ptp_clock_info * ptp,s64 delta)170*4882a593Smuzhiyun static int ptp_dte_adjtime(struct ptp_clock_info *ptp, s64 delta)
171*4882a593Smuzhiyun {
172*4882a593Smuzhiyun 	unsigned long flags;
173*4882a593Smuzhiyun 	struct ptp_dte *ptp_dte = container_of(ptp, struct ptp_dte, caps);
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	spin_lock_irqsave(&ptp_dte->lock, flags);
176*4882a593Smuzhiyun 	dte_write_nco_delta(ptp_dte, delta);
177*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ptp_dte->lock, flags);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	return 0;
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun 
ptp_dte_gettime(struct ptp_clock_info * ptp,struct timespec64 * ts)182*4882a593Smuzhiyun static int ptp_dte_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
183*4882a593Smuzhiyun {
184*4882a593Smuzhiyun 	unsigned long flags;
185*4882a593Smuzhiyun 	struct ptp_dte *ptp_dte = container_of(ptp, struct ptp_dte, caps);
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	spin_lock_irqsave(&ptp_dte->lock, flags);
188*4882a593Smuzhiyun 	*ts = ns_to_timespec64(dte_read_nco_with_ovf(ptp_dte));
189*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ptp_dte->lock, flags);
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	return 0;
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun 
ptp_dte_settime(struct ptp_clock_info * ptp,const struct timespec64 * ts)194*4882a593Smuzhiyun static int ptp_dte_settime(struct ptp_clock_info *ptp,
195*4882a593Smuzhiyun 			     const struct timespec64 *ts)
196*4882a593Smuzhiyun {
197*4882a593Smuzhiyun 	unsigned long flags;
198*4882a593Smuzhiyun 	struct ptp_dte *ptp_dte = container_of(ptp, struct ptp_dte, caps);
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	spin_lock_irqsave(&ptp_dte->lock, flags);
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun 	/* Disable nco increment */
203*4882a593Smuzhiyun 	writel(0, ptp_dte->regs + DTE_NCO_INC_REG);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 	dte_write_nco(ptp_dte->regs, timespec64_to_ns(ts));
206*4882a593Smuzhiyun 
207*4882a593Smuzhiyun 	/* reset overflow and wrap counter */
208*4882a593Smuzhiyun 	ptp_dte->ts_ovf_last = 0;
209*4882a593Smuzhiyun 	ptp_dte->ts_wrap_cnt = 0;
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 	/* Enable nco increment */
212*4882a593Smuzhiyun 	writel(DTE_NCO_INC_DEFAULT, ptp_dte->regs + DTE_NCO_INC_REG);
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	spin_unlock_irqrestore(&ptp_dte->lock, flags);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	return 0;
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
ptp_dte_enable(struct ptp_clock_info * ptp,struct ptp_clock_request * rq,int on)219*4882a593Smuzhiyun static int ptp_dte_enable(struct ptp_clock_info *ptp,
220*4882a593Smuzhiyun 			    struct ptp_clock_request *rq, int on)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun 	return -EOPNOTSUPP;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun static const struct ptp_clock_info ptp_dte_caps = {
226*4882a593Smuzhiyun 	.owner		= THIS_MODULE,
227*4882a593Smuzhiyun 	.name		= "DTE PTP timer",
228*4882a593Smuzhiyun 	.max_adj	= 50000000,
229*4882a593Smuzhiyun 	.n_ext_ts	= 0,
230*4882a593Smuzhiyun 	.n_pins		= 0,
231*4882a593Smuzhiyun 	.pps		= 0,
232*4882a593Smuzhiyun 	.adjfreq	= ptp_dte_adjfreq,
233*4882a593Smuzhiyun 	.adjtime	= ptp_dte_adjtime,
234*4882a593Smuzhiyun 	.gettime64	= ptp_dte_gettime,
235*4882a593Smuzhiyun 	.settime64	= ptp_dte_settime,
236*4882a593Smuzhiyun 	.enable		= ptp_dte_enable,
237*4882a593Smuzhiyun };
238*4882a593Smuzhiyun 
ptp_dte_probe(struct platform_device * pdev)239*4882a593Smuzhiyun static int ptp_dte_probe(struct platform_device *pdev)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun 	struct ptp_dte *ptp_dte;
242*4882a593Smuzhiyun 	struct device *dev = &pdev->dev;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	ptp_dte = devm_kzalloc(dev, sizeof(struct ptp_dte), GFP_KERNEL);
245*4882a593Smuzhiyun 	if (!ptp_dte)
246*4882a593Smuzhiyun 		return -ENOMEM;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	ptp_dte->regs = devm_platform_ioremap_resource(pdev, 0);
249*4882a593Smuzhiyun 	if (IS_ERR(ptp_dte->regs))
250*4882a593Smuzhiyun 		return PTR_ERR(ptp_dte->regs);
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	spin_lock_init(&ptp_dte->lock);
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	ptp_dte->dev = dev;
255*4882a593Smuzhiyun 	ptp_dte->caps = ptp_dte_caps;
256*4882a593Smuzhiyun 	ptp_dte->ptp_clk = ptp_clock_register(&ptp_dte->caps, &pdev->dev);
257*4882a593Smuzhiyun 	if (IS_ERR(ptp_dte->ptp_clk)) {
258*4882a593Smuzhiyun 		dev_err(dev,
259*4882a593Smuzhiyun 			"%s: Failed to register ptp clock\n", __func__);
260*4882a593Smuzhiyun 		return PTR_ERR(ptp_dte->ptp_clk);
261*4882a593Smuzhiyun 	}
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	platform_set_drvdata(pdev, ptp_dte);
264*4882a593Smuzhiyun 
265*4882a593Smuzhiyun 	dev_info(dev, "ptp clk probe done\n");
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	return 0;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
ptp_dte_remove(struct platform_device * pdev)270*4882a593Smuzhiyun static int ptp_dte_remove(struct platform_device *pdev)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	struct ptp_dte *ptp_dte = platform_get_drvdata(pdev);
273*4882a593Smuzhiyun 	u8 i;
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	ptp_clock_unregister(ptp_dte->ptp_clk);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	for (i = 0; i < DTE_NUM_REGS_TO_RESTORE; i++)
278*4882a593Smuzhiyun 		writel(0, ptp_dte->regs + (i * sizeof(u32)));
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	return 0;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
ptp_dte_suspend(struct device * dev)284*4882a593Smuzhiyun static int ptp_dte_suspend(struct device *dev)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun 	struct ptp_dte *ptp_dte = dev_get_drvdata(dev);
287*4882a593Smuzhiyun 	u8 i;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 	for (i = 0; i < DTE_NUM_REGS_TO_RESTORE; i++) {
290*4882a593Smuzhiyun 		ptp_dte->reg_val[i] =
291*4882a593Smuzhiyun 			readl(ptp_dte->regs + (i * sizeof(u32)));
292*4882a593Smuzhiyun 	}
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun 	/* disable the nco */
295*4882a593Smuzhiyun 	writel(0, ptp_dte->regs + DTE_NCO_INC_REG);
296*4882a593Smuzhiyun 
297*4882a593Smuzhiyun 	return 0;
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun 
ptp_dte_resume(struct device * dev)300*4882a593Smuzhiyun static int ptp_dte_resume(struct device *dev)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun 	struct ptp_dte *ptp_dte = dev_get_drvdata(dev);
303*4882a593Smuzhiyun 	u8 i;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	for (i = 0; i < DTE_NUM_REGS_TO_RESTORE; i++) {
306*4882a593Smuzhiyun 		if ((i * sizeof(u32)) != DTE_NCO_OVERFLOW_REG)
307*4882a593Smuzhiyun 			writel(ptp_dte->reg_val[i],
308*4882a593Smuzhiyun 				(ptp_dte->regs + (i * sizeof(u32))));
309*4882a593Smuzhiyun 		else
310*4882a593Smuzhiyun 			writel(((ptp_dte->reg_val[i] &
311*4882a593Smuzhiyun 				DTE_NCO_SUM3_MASK) << DTE_NCO_SUM3_WR_SHIFT),
312*4882a593Smuzhiyun 				(ptp_dte->regs + (i * sizeof(u32))));
313*4882a593Smuzhiyun 	}
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun 	return 0;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun static const struct dev_pm_ops ptp_dte_pm_ops = {
319*4882a593Smuzhiyun 	.suspend = ptp_dte_suspend,
320*4882a593Smuzhiyun 	.resume = ptp_dte_resume
321*4882a593Smuzhiyun };
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun #define PTP_DTE_PM_OPS	(&ptp_dte_pm_ops)
324*4882a593Smuzhiyun #else
325*4882a593Smuzhiyun #define PTP_DTE_PM_OPS	NULL
326*4882a593Smuzhiyun #endif
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun static const struct of_device_id ptp_dte_of_match[] = {
329*4882a593Smuzhiyun 	{ .compatible = "brcm,ptp-dte", },
330*4882a593Smuzhiyun 	{},
331*4882a593Smuzhiyun };
332*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, ptp_dte_of_match);
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun static struct platform_driver ptp_dte_driver = {
335*4882a593Smuzhiyun 	.driver = {
336*4882a593Smuzhiyun 		.name = "ptp-dte",
337*4882a593Smuzhiyun 		.pm = PTP_DTE_PM_OPS,
338*4882a593Smuzhiyun 		.of_match_table = ptp_dte_of_match,
339*4882a593Smuzhiyun 	},
340*4882a593Smuzhiyun 	.probe    = ptp_dte_probe,
341*4882a593Smuzhiyun 	.remove   = ptp_dte_remove,
342*4882a593Smuzhiyun };
343*4882a593Smuzhiyun module_platform_driver(ptp_dte_driver);
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun MODULE_AUTHOR("Broadcom");
346*4882a593Smuzhiyun MODULE_DESCRIPTION("Broadcom DTE PTP Clock driver");
347*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
348