Commit | Line | Data |
---|---|---|
c78275f3 | 1 | /* |
ceefc71d | 2 | * PTP 1588 clock for Freescale QorIQ 1588 timer |
c78275f3 RC |
3 | * |
4 | * Copyright (C) 2010 OMICRON electronics GmbH | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program; if not, write to the Free Software | |
18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
19 | */ | |
375d6a1b JP |
20 | |
21 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | |
22 | ||
c78275f3 RC |
23 | #include <linux/device.h> |
24 | #include <linux/hrtimer.h> | |
c78275f3 RC |
25 | #include <linux/interrupt.h> |
26 | #include <linux/kernel.h> | |
27 | #include <linux/module.h> | |
28 | #include <linux/of.h> | |
29 | #include <linux/of_platform.h> | |
30 | #include <linux/timex.h> | |
ceefc71d | 31 | #include <linux/slab.h> |
c78275f3 | 32 | |
6c50c1ed | 33 | #include <linux/fsl/ptp_qoriq.h> |
ceefc71d | 34 | |
c78275f3 RC |
35 | /* |
36 | * Register access functions | |
37 | */ | |
38 | ||
ceefc71d YL |
39 | /* Caller must hold qoriq_ptp->lock. */ |
40 | static u64 tmr_cnt_read(struct qoriq_ptp *qoriq_ptp) | |
c78275f3 RC |
41 | { |
42 | u64 ns; | |
43 | u32 lo, hi; | |
44 | ||
ceefc71d YL |
45 | lo = qoriq_read(&qoriq_ptp->regs->tmr_cnt_l); |
46 | hi = qoriq_read(&qoriq_ptp->regs->tmr_cnt_h); | |
c78275f3 RC |
47 | ns = ((u64) hi) << 32; |
48 | ns |= lo; | |
49 | return ns; | |
50 | } | |
51 | ||
ceefc71d YL |
52 | /* Caller must hold qoriq_ptp->lock. */ |
53 | static void tmr_cnt_write(struct qoriq_ptp *qoriq_ptp, u64 ns) | |
c78275f3 RC |
54 | { |
55 | u32 hi = ns >> 32; | |
56 | u32 lo = ns & 0xffffffff; | |
57 | ||
ceefc71d YL |
58 | qoriq_write(&qoriq_ptp->regs->tmr_cnt_l, lo); |
59 | qoriq_write(&qoriq_ptp->regs->tmr_cnt_h, hi); | |
c78275f3 RC |
60 | } |
61 | ||
ceefc71d YL |
62 | /* Caller must hold qoriq_ptp->lock. */ |
63 | static void set_alarm(struct qoriq_ptp *qoriq_ptp) | |
c78275f3 RC |
64 | { |
65 | u64 ns; | |
66 | u32 lo, hi; | |
67 | ||
ceefc71d | 68 | ns = tmr_cnt_read(qoriq_ptp) + 1500000000ULL; |
c78275f3 | 69 | ns = div_u64(ns, 1000000000UL) * 1000000000ULL; |
ceefc71d | 70 | ns -= qoriq_ptp->tclk_period; |
c78275f3 RC |
71 | hi = ns >> 32; |
72 | lo = ns & 0xffffffff; | |
ceefc71d YL |
73 | qoriq_write(&qoriq_ptp->regs->tmr_alarm1_l, lo); |
74 | qoriq_write(&qoriq_ptp->regs->tmr_alarm1_h, hi); | |
c78275f3 RC |
75 | } |
76 | ||
ceefc71d YL |
77 | /* Caller must hold qoriq_ptp->lock. */ |
78 | static void set_fipers(struct qoriq_ptp *qoriq_ptp) | |
c78275f3 | 79 | { |
ceefc71d YL |
80 | set_alarm(qoriq_ptp); |
81 | qoriq_write(&qoriq_ptp->regs->tmr_fiper1, qoriq_ptp->tmr_fiper1); | |
82 | qoriq_write(&qoriq_ptp->regs->tmr_fiper2, qoriq_ptp->tmr_fiper2); | |
c78275f3 RC |
83 | } |
84 | ||
85 | /* | |
86 | * Interrupt service routine | |
87 | */ | |
88 | ||
89 | static irqreturn_t isr(int irq, void *priv) | |
90 | { | |
ceefc71d | 91 | struct qoriq_ptp *qoriq_ptp = priv; |
c78275f3 RC |
92 | struct ptp_clock_event event; |
93 | u64 ns; | |
94 | u32 ack = 0, lo, hi, mask, val; | |
95 | ||
ceefc71d | 96 | val = qoriq_read(&qoriq_ptp->regs->tmr_tevent); |
c78275f3 RC |
97 | |
98 | if (val & ETS1) { | |
99 | ack |= ETS1; | |
ceefc71d YL |
100 | hi = qoriq_read(&qoriq_ptp->regs->tmr_etts1_h); |
101 | lo = qoriq_read(&qoriq_ptp->regs->tmr_etts1_l); | |
c78275f3 RC |
102 | event.type = PTP_CLOCK_EXTTS; |
103 | event.index = 0; | |
104 | event.timestamp = ((u64) hi) << 32; | |
105 | event.timestamp |= lo; | |
ceefc71d | 106 | ptp_clock_event(qoriq_ptp->clock, &event); |
c78275f3 RC |
107 | } |
108 | ||
109 | if (val & ETS2) { | |
110 | ack |= ETS2; | |
ceefc71d YL |
111 | hi = qoriq_read(&qoriq_ptp->regs->tmr_etts2_h); |
112 | lo = qoriq_read(&qoriq_ptp->regs->tmr_etts2_l); | |
c78275f3 RC |
113 | event.type = PTP_CLOCK_EXTTS; |
114 | event.index = 1; | |
115 | event.timestamp = ((u64) hi) << 32; | |
116 | event.timestamp |= lo; | |
ceefc71d | 117 | ptp_clock_event(qoriq_ptp->clock, &event); |
c78275f3 RC |
118 | } |
119 | ||
120 | if (val & ALM2) { | |
121 | ack |= ALM2; | |
ceefc71d | 122 | if (qoriq_ptp->alarm_value) { |
c78275f3 RC |
123 | event.type = PTP_CLOCK_ALARM; |
124 | event.index = 0; | |
ceefc71d YL |
125 | event.timestamp = qoriq_ptp->alarm_value; |
126 | ptp_clock_event(qoriq_ptp->clock, &event); | |
c78275f3 | 127 | } |
ceefc71d YL |
128 | if (qoriq_ptp->alarm_interval) { |
129 | ns = qoriq_ptp->alarm_value + qoriq_ptp->alarm_interval; | |
c78275f3 RC |
130 | hi = ns >> 32; |
131 | lo = ns & 0xffffffff; | |
ceefc71d YL |
132 | spin_lock(&qoriq_ptp->lock); |
133 | qoriq_write(&qoriq_ptp->regs->tmr_alarm2_l, lo); | |
134 | qoriq_write(&qoriq_ptp->regs->tmr_alarm2_h, hi); | |
135 | spin_unlock(&qoriq_ptp->lock); | |
136 | qoriq_ptp->alarm_value = ns; | |
c78275f3 | 137 | } else { |
ceefc71d YL |
138 | qoriq_write(&qoriq_ptp->regs->tmr_tevent, ALM2); |
139 | spin_lock(&qoriq_ptp->lock); | |
140 | mask = qoriq_read(&qoriq_ptp->regs->tmr_temask); | |
c78275f3 | 141 | mask &= ~ALM2EN; |
ceefc71d YL |
142 | qoriq_write(&qoriq_ptp->regs->tmr_temask, mask); |
143 | spin_unlock(&qoriq_ptp->lock); | |
144 | qoriq_ptp->alarm_value = 0; | |
145 | qoriq_ptp->alarm_interval = 0; | |
c78275f3 RC |
146 | } |
147 | } | |
148 | ||
149 | if (val & PP1) { | |
150 | ack |= PP1; | |
151 | event.type = PTP_CLOCK_PPS; | |
ceefc71d | 152 | ptp_clock_event(qoriq_ptp->clock, &event); |
c78275f3 RC |
153 | } |
154 | ||
155 | if (ack) { | |
ceefc71d | 156 | qoriq_write(&qoriq_ptp->regs->tmr_tevent, ack); |
c78275f3 RC |
157 | return IRQ_HANDLED; |
158 | } else | |
159 | return IRQ_NONE; | |
160 | } | |
161 | ||
162 | /* | |
163 | * PTP clock operations | |
164 | */ | |
165 | ||
ceefc71d | 166 | static int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) |
c78275f3 | 167 | { |
42895116 UDB |
168 | u64 adj, diff; |
169 | u32 tmr_add; | |
c78275f3 | 170 | int neg_adj = 0; |
ceefc71d | 171 | struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); |
c78275f3 | 172 | |
42895116 | 173 | if (scaled_ppm < 0) { |
c78275f3 | 174 | neg_adj = 1; |
42895116 | 175 | scaled_ppm = -scaled_ppm; |
c78275f3 | 176 | } |
ceefc71d | 177 | tmr_add = qoriq_ptp->tmr_add; |
c78275f3 | 178 | adj = tmr_add; |
42895116 UDB |
179 | |
180 | /* calculate diff as adj*(scaled_ppm/65536)/1000000 | |
181 | * and round() to the nearest integer | |
182 | */ | |
183 | adj *= scaled_ppm; | |
184 | diff = div_u64(adj, 8000000); | |
185 | diff = (diff >> 13) + ((diff >> 12) & 1); | |
c78275f3 RC |
186 | |
187 | tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff; | |
188 | ||
ceefc71d | 189 | qoriq_write(&qoriq_ptp->regs->tmr_add, tmr_add); |
c78275f3 RC |
190 | |
191 | return 0; | |
192 | } | |
193 | ||
ceefc71d | 194 | static int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta) |
c78275f3 RC |
195 | { |
196 | s64 now; | |
197 | unsigned long flags; | |
ceefc71d | 198 | struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); |
c78275f3 | 199 | |
ceefc71d | 200 | spin_lock_irqsave(&qoriq_ptp->lock, flags); |
c78275f3 | 201 | |
ceefc71d | 202 | now = tmr_cnt_read(qoriq_ptp); |
c78275f3 | 203 | now += delta; |
ceefc71d YL |
204 | tmr_cnt_write(qoriq_ptp, now); |
205 | set_fipers(qoriq_ptp); | |
c78275f3 | 206 | |
ceefc71d | 207 | spin_unlock_irqrestore(&qoriq_ptp->lock, flags); |
c78275f3 | 208 | |
c78275f3 RC |
209 | return 0; |
210 | } | |
211 | ||
ceefc71d | 212 | static int ptp_qoriq_gettime(struct ptp_clock_info *ptp, |
d28fdf0f | 213 | struct timespec64 *ts) |
c78275f3 RC |
214 | { |
215 | u64 ns; | |
c78275f3 | 216 | unsigned long flags; |
ceefc71d | 217 | struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); |
c78275f3 | 218 | |
ceefc71d | 219 | spin_lock_irqsave(&qoriq_ptp->lock, flags); |
c78275f3 | 220 | |
ceefc71d | 221 | ns = tmr_cnt_read(qoriq_ptp); |
c78275f3 | 222 | |
ceefc71d | 223 | spin_unlock_irqrestore(&qoriq_ptp->lock, flags); |
c78275f3 | 224 | |
3359e7c2 RC |
225 | *ts = ns_to_timespec64(ns); |
226 | ||
c78275f3 RC |
227 | return 0; |
228 | } | |
229 | ||
ceefc71d | 230 | static int ptp_qoriq_settime(struct ptp_clock_info *ptp, |
d28fdf0f | 231 | const struct timespec64 *ts) |
c78275f3 RC |
232 | { |
233 | u64 ns; | |
234 | unsigned long flags; | |
ceefc71d | 235 | struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); |
c78275f3 | 236 | |
3359e7c2 | 237 | ns = timespec64_to_ns(ts); |
c78275f3 | 238 | |
ceefc71d | 239 | spin_lock_irqsave(&qoriq_ptp->lock, flags); |
c78275f3 | 240 | |
ceefc71d YL |
241 | tmr_cnt_write(qoriq_ptp, ns); |
242 | set_fipers(qoriq_ptp); | |
c78275f3 | 243 | |
ceefc71d | 244 | spin_unlock_irqrestore(&qoriq_ptp->lock, flags); |
c78275f3 RC |
245 | |
246 | return 0; | |
247 | } | |
248 | ||
ceefc71d | 249 | static int ptp_qoriq_enable(struct ptp_clock_info *ptp, |
c78275f3 RC |
250 | struct ptp_clock_request *rq, int on) |
251 | { | |
ceefc71d | 252 | struct qoriq_ptp *qoriq_ptp = container_of(ptp, struct qoriq_ptp, caps); |
c78275f3 RC |
253 | unsigned long flags; |
254 | u32 bit, mask; | |
255 | ||
256 | switch (rq->type) { | |
257 | case PTP_CLK_REQ_EXTTS: | |
258 | switch (rq->extts.index) { | |
259 | case 0: | |
260 | bit = ETS1EN; | |
261 | break; | |
262 | case 1: | |
263 | bit = ETS2EN; | |
264 | break; | |
265 | default: | |
266 | return -EINVAL; | |
267 | } | |
ceefc71d YL |
268 | spin_lock_irqsave(&qoriq_ptp->lock, flags); |
269 | mask = qoriq_read(&qoriq_ptp->regs->tmr_temask); | |
c78275f3 RC |
270 | if (on) |
271 | mask |= bit; | |
272 | else | |
273 | mask &= ~bit; | |
ceefc71d YL |
274 | qoriq_write(&qoriq_ptp->regs->tmr_temask, mask); |
275 | spin_unlock_irqrestore(&qoriq_ptp->lock, flags); | |
c78275f3 RC |
276 | return 0; |
277 | ||
278 | case PTP_CLK_REQ_PPS: | |
ceefc71d YL |
279 | spin_lock_irqsave(&qoriq_ptp->lock, flags); |
280 | mask = qoriq_read(&qoriq_ptp->regs->tmr_temask); | |
c78275f3 RC |
281 | if (on) |
282 | mask |= PP1EN; | |
283 | else | |
284 | mask &= ~PP1EN; | |
ceefc71d YL |
285 | qoriq_write(&qoriq_ptp->regs->tmr_temask, mask); |
286 | spin_unlock_irqrestore(&qoriq_ptp->lock, flags); | |
c78275f3 RC |
287 | return 0; |
288 | ||
289 | default: | |
290 | break; | |
291 | } | |
292 | ||
293 | return -EOPNOTSUPP; | |
294 | } | |
295 | ||
ceefc71d | 296 | static const struct ptp_clock_info ptp_qoriq_caps = { |
c78275f3 | 297 | .owner = THIS_MODULE, |
ceefc71d | 298 | .name = "qoriq ptp clock", |
c78275f3 | 299 | .max_adj = 512000, |
cd4baaaa | 300 | .n_alarm = 0, |
c78275f3 RC |
301 | .n_ext_ts = N_EXT_TS, |
302 | .n_per_out = 0, | |
4986b4f0 | 303 | .n_pins = 0, |
c78275f3 | 304 | .pps = 1, |
ceefc71d YL |
305 | .adjfine = ptp_qoriq_adjfine, |
306 | .adjtime = ptp_qoriq_adjtime, | |
307 | .gettime64 = ptp_qoriq_gettime, | |
308 | .settime64 = ptp_qoriq_settime, | |
309 | .enable = ptp_qoriq_enable, | |
c78275f3 RC |
310 | }; |
311 | ||
ceefc71d | 312 | static int qoriq_ptp_probe(struct platform_device *dev) |
c78275f3 RC |
313 | { |
314 | struct device_node *node = dev->dev.of_node; | |
ceefc71d | 315 | struct qoriq_ptp *qoriq_ptp; |
d28fdf0f | 316 | struct timespec64 now; |
c78275f3 RC |
317 | int err = -ENOMEM; |
318 | u32 tmr_ctrl; | |
319 | unsigned long flags; | |
320 | ||
ceefc71d YL |
321 | qoriq_ptp = kzalloc(sizeof(*qoriq_ptp), GFP_KERNEL); |
322 | if (!qoriq_ptp) | |
c78275f3 RC |
323 | goto no_memory; |
324 | ||
325 | err = -ENODEV; | |
326 | ||
ceefc71d | 327 | qoriq_ptp->caps = ptp_qoriq_caps; |
e58f6f4f | 328 | |
ceefc71d YL |
329 | if (of_property_read_u32(node, "fsl,cksel", &qoriq_ptp->cksel)) |
330 | qoriq_ptp->cksel = DEFAULT_CKSEL; | |
c78275f3 | 331 | |
c35ec779 | 332 | if (of_property_read_u32(node, |
ceefc71d | 333 | "fsl,tclk-period", &qoriq_ptp->tclk_period) || |
c35ec779 | 334 | of_property_read_u32(node, |
ceefc71d | 335 | "fsl,tmr-prsc", &qoriq_ptp->tmr_prsc) || |
c35ec779 | 336 | of_property_read_u32(node, |
ceefc71d | 337 | "fsl,tmr-add", &qoriq_ptp->tmr_add) || |
c35ec779 | 338 | of_property_read_u32(node, |
ceefc71d | 339 | "fsl,tmr-fiper1", &qoriq_ptp->tmr_fiper1) || |
c35ec779 | 340 | of_property_read_u32(node, |
ceefc71d | 341 | "fsl,tmr-fiper2", &qoriq_ptp->tmr_fiper2) || |
c35ec779 | 342 | of_property_read_u32(node, |
ceefc71d | 343 | "fsl,max-adj", &qoriq_ptp->caps.max_adj)) { |
c78275f3 RC |
344 | pr_err("device tree node missing required elements\n"); |
345 | goto no_node; | |
346 | } | |
347 | ||
ceefc71d | 348 | qoriq_ptp->irq = platform_get_irq(dev, 0); |
c78275f3 | 349 | |
ceefc71d | 350 | if (qoriq_ptp->irq < 0) { |
c78275f3 RC |
351 | pr_err("irq not in device tree\n"); |
352 | goto no_node; | |
353 | } | |
ceefc71d | 354 | if (request_irq(qoriq_ptp->irq, isr, 0, DRIVER, qoriq_ptp)) { |
c78275f3 RC |
355 | pr_err("request_irq failed\n"); |
356 | goto no_node; | |
357 | } | |
358 | ||
ceefc71d YL |
359 | qoriq_ptp->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0); |
360 | if (!qoriq_ptp->rsrc) { | |
c78275f3 RC |
361 | pr_err("no resource\n"); |
362 | goto no_resource; | |
363 | } | |
ceefc71d | 364 | if (request_resource(&iomem_resource, qoriq_ptp->rsrc)) { |
c78275f3 RC |
365 | pr_err("resource busy\n"); |
366 | goto no_resource; | |
367 | } | |
368 | ||
ceefc71d | 369 | spin_lock_init(&qoriq_ptp->lock); |
c78275f3 | 370 | |
ceefc71d YL |
371 | qoriq_ptp->regs = ioremap(qoriq_ptp->rsrc->start, |
372 | resource_size(qoriq_ptp->rsrc)); | |
373 | if (!qoriq_ptp->regs) { | |
c78275f3 RC |
374 | pr_err("ioremap ptp registers failed\n"); |
375 | goto no_ioremap; | |
376 | } | |
f696a21c | 377 | ktime_get_real_ts64(&now); |
ceefc71d | 378 | ptp_qoriq_settime(&qoriq_ptp->caps, &now); |
c78275f3 RC |
379 | |
380 | tmr_ctrl = | |
ceefc71d YL |
381 | (qoriq_ptp->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT | |
382 | (qoriq_ptp->cksel & CKSEL_MASK) << CKSEL_SHIFT; | |
c78275f3 | 383 | |
ceefc71d | 384 | spin_lock_irqsave(&qoriq_ptp->lock, flags); |
c78275f3 | 385 | |
ceefc71d YL |
386 | qoriq_write(&qoriq_ptp->regs->tmr_ctrl, tmr_ctrl); |
387 | qoriq_write(&qoriq_ptp->regs->tmr_add, qoriq_ptp->tmr_add); | |
388 | qoriq_write(&qoriq_ptp->regs->tmr_prsc, qoriq_ptp->tmr_prsc); | |
389 | qoriq_write(&qoriq_ptp->regs->tmr_fiper1, qoriq_ptp->tmr_fiper1); | |
390 | qoriq_write(&qoriq_ptp->regs->tmr_fiper2, qoriq_ptp->tmr_fiper2); | |
391 | set_alarm(qoriq_ptp); | |
392 | qoriq_write(&qoriq_ptp->regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD); | |
c78275f3 | 393 | |
ceefc71d | 394 | spin_unlock_irqrestore(&qoriq_ptp->lock, flags); |
c78275f3 | 395 | |
ceefc71d YL |
396 | qoriq_ptp->clock = ptp_clock_register(&qoriq_ptp->caps, &dev->dev); |
397 | if (IS_ERR(qoriq_ptp->clock)) { | |
398 | err = PTR_ERR(qoriq_ptp->clock); | |
c78275f3 RC |
399 | goto no_clock; |
400 | } | |
ceefc71d | 401 | qoriq_ptp->phc_index = ptp_clock_index(qoriq_ptp->clock); |
c78275f3 | 402 | |
ceefc71d | 403 | platform_set_drvdata(dev, qoriq_ptp); |
c78275f3 RC |
404 | |
405 | return 0; | |
406 | ||
407 | no_clock: | |
ceefc71d | 408 | iounmap(qoriq_ptp->regs); |
c78275f3 | 409 | no_ioremap: |
ceefc71d | 410 | release_resource(qoriq_ptp->rsrc); |
c78275f3 | 411 | no_resource: |
ceefc71d | 412 | free_irq(qoriq_ptp->irq, qoriq_ptp); |
c78275f3 | 413 | no_node: |
ceefc71d | 414 | kfree(qoriq_ptp); |
c78275f3 RC |
415 | no_memory: |
416 | return err; | |
417 | } | |
418 | ||
ceefc71d | 419 | static int qoriq_ptp_remove(struct platform_device *dev) |
c78275f3 | 420 | { |
ceefc71d | 421 | struct qoriq_ptp *qoriq_ptp = platform_get_drvdata(dev); |
c78275f3 | 422 | |
ceefc71d YL |
423 | qoriq_write(&qoriq_ptp->regs->tmr_temask, 0); |
424 | qoriq_write(&qoriq_ptp->regs->tmr_ctrl, 0); | |
c78275f3 | 425 | |
ceefc71d YL |
426 | ptp_clock_unregister(qoriq_ptp->clock); |
427 | iounmap(qoriq_ptp->regs); | |
428 | release_resource(qoriq_ptp->rsrc); | |
429 | free_irq(qoriq_ptp->irq, qoriq_ptp); | |
430 | kfree(qoriq_ptp); | |
c78275f3 RC |
431 | |
432 | return 0; | |
433 | } | |
434 | ||
94e5a2a8 | 435 | static const struct of_device_id match_table[] = { |
c78275f3 RC |
436 | { .compatible = "fsl,etsec-ptp" }, |
437 | {}, | |
438 | }; | |
23860063 | 439 | MODULE_DEVICE_TABLE(of, match_table); |
c78275f3 | 440 | |
ceefc71d | 441 | static struct platform_driver qoriq_ptp_driver = { |
c78275f3 | 442 | .driver = { |
ceefc71d | 443 | .name = "ptp_qoriq", |
c78275f3 | 444 | .of_match_table = match_table, |
c78275f3 | 445 | }, |
ceefc71d YL |
446 | .probe = qoriq_ptp_probe, |
447 | .remove = qoriq_ptp_remove, | |
c78275f3 RC |
448 | }; |
449 | ||
ceefc71d | 450 | module_platform_driver(qoriq_ptp_driver); |
c78275f3 | 451 | |
c2ec3ff6 | 452 | MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>"); |
ceefc71d | 453 | MODULE_DESCRIPTION("PTP clock for Freescale QorIQ 1588 timer"); |
c78275f3 | 454 | MODULE_LICENSE("GPL"); |