Blame view
drivers/ptp/ptp_qoriq.c
15.5 KB
74ba9207e treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
c78275f36 ptp: Added a cloc... |
2 |
/* |
ceefc71d4 ptp: rework gianf... |
3 |
* PTP 1588 clock for Freescale QorIQ 1588 timer |
c78275f36 ptp: Added a cloc... |
4 5 |
* * Copyright (C) 2010 OMICRON electronics GmbH |
c78275f36 ptp: Added a cloc... |
6 |
*/ |
375d6a1b4 gianfar: Use netd... |
7 8 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
c78275f36 ptp: Added a cloc... |
9 10 |
#include <linux/device.h> #include <linux/hrtimer.h> |
c78275f36 ptp: Added a cloc... |
11 12 13 14 15 |
#include <linux/kernel.h> #include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> #include <linux/timex.h> |
ceefc71d4 ptp: rework gianf... |
16 |
#include <linux/slab.h> |
91305f281 ptp_qoriq: suppor... |
17 |
#include <linux/clk.h> |
c78275f36 ptp: Added a cloc... |
18 |
|
6c50c1ed7 ptp_qoriq: move s... |
19 |
#include <linux/fsl/ptp_qoriq.h> |
ceefc71d4 ptp: rework gianf... |
20 |
|
c78275f36 ptp: Added a cloc... |
21 22 23 |
/* * Register access functions */ |
1e562c815 ptp_qoriq: make s... |
24 25 |
/* Caller must hold ptp_qoriq->lock. */ static u64 tmr_cnt_read(struct ptp_qoriq *ptp_qoriq) |
c78275f36 ptp: Added a cloc... |
26 |
{ |
1e562c815 ptp_qoriq: make s... |
27 |
struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; |
c78275f36 ptp: Added a cloc... |
28 29 |
u64 ns; u32 lo, hi; |
f038ddf25 ptp_qoriq: add li... |
30 31 |
lo = ptp_qoriq->read(®s->ctrl_regs->tmr_cnt_l); hi = ptp_qoriq->read(®s->ctrl_regs->tmr_cnt_h); |
c78275f36 ptp: Added a cloc... |
32 33 34 35 |
ns = ((u64) hi) << 32; ns |= lo; return ns; } |
1e562c815 ptp_qoriq: make s... |
36 37 |
/* Caller must hold ptp_qoriq->lock. */ static void tmr_cnt_write(struct ptp_qoriq *ptp_qoriq, u64 ns) |
c78275f36 ptp: Added a cloc... |
38 |
{ |
1e562c815 ptp_qoriq: make s... |
39 |
struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; |
c78275f36 ptp: Added a cloc... |
40 41 |
u32 hi = ns >> 32; u32 lo = ns & 0xffffffff; |
f038ddf25 ptp_qoriq: add li... |
42 43 |
ptp_qoriq->write(®s->ctrl_regs->tmr_cnt_l, lo); ptp_qoriq->write(®s->ctrl_regs->tmr_cnt_h, hi); |
c78275f36 ptp: Added a cloc... |
44 |
} |
1e562c815 ptp_qoriq: make s... |
45 46 |
/* Caller must hold ptp_qoriq->lock. */ static void set_alarm(struct ptp_qoriq *ptp_qoriq) |
c78275f36 ptp: Added a cloc... |
47 |
{ |
1e562c815 ptp_qoriq: make s... |
48 |
struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; |
c78275f36 ptp: Added a cloc... |
49 50 |
u64 ns; u32 lo, hi; |
1e562c815 ptp_qoriq: make s... |
51 |
ns = tmr_cnt_read(ptp_qoriq) + 1500000000ULL; |
c78275f36 ptp: Added a cloc... |
52 |
ns = div_u64(ns, 1000000000UL) * 1000000000ULL; |
1e562c815 ptp_qoriq: make s... |
53 |
ns -= ptp_qoriq->tclk_period; |
c78275f36 ptp: Added a cloc... |
54 55 |
hi = ns >> 32; lo = ns & 0xffffffff; |
f038ddf25 ptp_qoriq: add li... |
56 57 |
ptp_qoriq->write(®s->alarm_regs->tmr_alarm1_l, lo); ptp_qoriq->write(®s->alarm_regs->tmr_alarm1_h, hi); |
c78275f36 ptp: Added a cloc... |
58 |
} |
1e562c815 ptp_qoriq: make s... |
59 60 |
/* Caller must hold ptp_qoriq->lock. */ static void set_fipers(struct ptp_qoriq *ptp_qoriq) |
c78275f36 ptp: Added a cloc... |
61 |
{ |
1e562c815 ptp_qoriq: make s... |
62 |
struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; |
a8f62d0c6 ptp: support DPAA... |
63 |
|
1e562c815 ptp_qoriq: make s... |
64 |
set_alarm(ptp_qoriq); |
f038ddf25 ptp_qoriq: add li... |
65 66 |
ptp_qoriq->write(®s->fiper_regs->tmr_fiper1, ptp_qoriq->tmr_fiper1); ptp_qoriq->write(®s->fiper_regs->tmr_fiper2, ptp_qoriq->tmr_fiper2); |
6d23d831e ptp_qoriq: suppor... |
67 68 69 70 |
if (ptp_qoriq->fiper3_support) ptp_qoriq->write(®s->fiper_regs->tmr_fiper3, ptp_qoriq->tmr_fiper3); |
c78275f36 ptp: Added a cloc... |
71 |
} |
9429439f5 ptp_qoriq: export... |
72 |
int extts_clean_up(struct ptp_qoriq *ptp_qoriq, int index, bool update_event) |
6815d8b09 ptp_qoriq: suppor... |
73 |
{ |
1e562c815 ptp_qoriq: make s... |
74 |
struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; |
6815d8b09 ptp_qoriq: suppor... |
75 76 77 |
struct ptp_clock_event event; void __iomem *reg_etts_l; void __iomem *reg_etts_h; |
10bc877c7 ptp_qoriq: check ... |
78 |
u32 valid, lo, hi; |
6815d8b09 ptp_qoriq: suppor... |
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
switch (index) { case 0: valid = ETS1_VLD; reg_etts_l = ®s->etts_regs->tmr_etts1_l; reg_etts_h = ®s->etts_regs->tmr_etts1_h; break; case 1: valid = ETS2_VLD; reg_etts_l = ®s->etts_regs->tmr_etts2_l; reg_etts_h = ®s->etts_regs->tmr_etts2_h; break; default: return -EINVAL; } event.type = PTP_CLOCK_EXTTS; event.index = index; |
10bc877c7 ptp_qoriq: check ... |
97 98 99 |
if (ptp_qoriq->extts_fifo_support) if (!(ptp_qoriq->read(®s->ctrl_regs->tmr_stat) & valid)) return 0; |
6815d8b09 ptp_qoriq: suppor... |
100 |
do { |
f038ddf25 ptp_qoriq: add li... |
101 102 |
lo = ptp_qoriq->read(reg_etts_l); hi = ptp_qoriq->read(reg_etts_h); |
6815d8b09 ptp_qoriq: suppor... |
103 104 105 106 |
if (update_event) { event.timestamp = ((u64) hi) << 32; event.timestamp |= lo; |
1e562c815 ptp_qoriq: make s... |
107 |
ptp_clock_event(ptp_qoriq->clock, &event); |
6815d8b09 ptp_qoriq: suppor... |
108 |
} |
10bc877c7 ptp_qoriq: check ... |
109 110 111 |
if (!ptp_qoriq->extts_fifo_support) break; } while (ptp_qoriq->read(®s->ctrl_regs->tmr_stat) & valid); |
6815d8b09 ptp_qoriq: suppor... |
112 113 114 |
return 0; } |
9429439f5 ptp_qoriq: export... |
115 |
EXPORT_SYMBOL_GPL(extts_clean_up); |
6815d8b09 ptp_qoriq: suppor... |
116 |
|
c78275f36 ptp: Added a cloc... |
117 118 119 |
/* * Interrupt service routine */ |
73356e4ea ptp_qoriq: make p... |
120 |
irqreturn_t ptp_qoriq_isr(int irq, void *priv) |
c78275f36 ptp: Added a cloc... |
121 |
{ |
1e562c815 ptp_qoriq: make s... |
122 123 |
struct ptp_qoriq *ptp_qoriq = priv; struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; |
c78275f36 ptp: Added a cloc... |
124 |
struct ptp_clock_event event; |
d71151a39 ptp_qoriq: drop t... |
125 |
u32 ack = 0, mask, val, irqs; |
b0bc10cc8 ptp_qoriq: fix in... |
126 |
|
1e562c815 ptp_qoriq: make s... |
127 |
spin_lock(&ptp_qoriq->lock); |
c78275f36 ptp: Added a cloc... |
128 |
|
f038ddf25 ptp_qoriq: add li... |
129 130 |
val = ptp_qoriq->read(®s->ctrl_regs->tmr_tevent); mask = ptp_qoriq->read(®s->ctrl_regs->tmr_temask); |
b0bc10cc8 ptp_qoriq: fix in... |
131 |
|
1e562c815 ptp_qoriq: make s... |
132 |
spin_unlock(&ptp_qoriq->lock); |
b0bc10cc8 ptp_qoriq: fix in... |
133 134 |
irqs = val & mask; |
c78275f36 ptp: Added a cloc... |
135 |
|
b0bc10cc8 ptp_qoriq: fix in... |
136 |
if (irqs & ETS1) { |
c78275f36 ptp: Added a cloc... |
137 |
ack |= ETS1; |
1e562c815 ptp_qoriq: make s... |
138 |
extts_clean_up(ptp_qoriq, 0, true); |
c78275f36 ptp: Added a cloc... |
139 |
} |
b0bc10cc8 ptp_qoriq: fix in... |
140 |
if (irqs & ETS2) { |
c78275f36 ptp: Added a cloc... |
141 |
ack |= ETS2; |
1e562c815 ptp_qoriq: make s... |
142 |
extts_clean_up(ptp_qoriq, 1, true); |
c78275f36 ptp: Added a cloc... |
143 |
} |
b0bc10cc8 ptp_qoriq: fix in... |
144 |
if (irqs & PP1) { |
c78275f36 ptp: Added a cloc... |
145 146 |
ack |= PP1; event.type = PTP_CLOCK_PPS; |
1e562c815 ptp_qoriq: make s... |
147 |
ptp_clock_event(ptp_qoriq->clock, &event); |
c78275f36 ptp: Added a cloc... |
148 149 150 |
} if (ack) { |
f038ddf25 ptp_qoriq: add li... |
151 |
ptp_qoriq->write(®s->ctrl_regs->tmr_tevent, ack); |
c78275f36 ptp: Added a cloc... |
152 153 154 155 |
return IRQ_HANDLED; } else return IRQ_NONE; } |
73356e4ea ptp_qoriq: make p... |
156 |
EXPORT_SYMBOL_GPL(ptp_qoriq_isr); |
c78275f36 ptp: Added a cloc... |
157 158 159 160 |
/* * PTP clock operations */ |
73356e4ea ptp_qoriq: make p... |
161 |
int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) |
c78275f36 ptp: Added a cloc... |
162 |
{ |
428951161 ptp: gianfar: Use... |
163 164 |
u64 adj, diff; u32 tmr_add; |
c78275f36 ptp: Added a cloc... |
165 |
int neg_adj = 0; |
1e562c815 ptp_qoriq: make s... |
166 167 |
struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps); struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; |
c78275f36 ptp: Added a cloc... |
168 |
|
428951161 ptp: gianfar: Use... |
169 |
if (scaled_ppm < 0) { |
c78275f36 ptp: Added a cloc... |
170 |
neg_adj = 1; |
428951161 ptp: gianfar: Use... |
171 |
scaled_ppm = -scaled_ppm; |
c78275f36 ptp: Added a cloc... |
172 |
} |
1e562c815 ptp_qoriq: make s... |
173 |
tmr_add = ptp_qoriq->tmr_add; |
c78275f36 ptp: Added a cloc... |
174 |
adj = tmr_add; |
428951161 ptp: gianfar: Use... |
175 176 177 178 179 180 181 |
/* calculate diff as adj*(scaled_ppm/65536)/1000000 * and round() to the nearest integer */ adj *= scaled_ppm; diff = div_u64(adj, 8000000); diff = (diff >> 13) + ((diff >> 12) & 1); |
c78275f36 ptp: Added a cloc... |
182 183 |
tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff; |
f038ddf25 ptp_qoriq: add li... |
184 |
ptp_qoriq->write(®s->ctrl_regs->tmr_add, tmr_add); |
c78275f36 ptp: Added a cloc... |
185 186 187 |
return 0; } |
73356e4ea ptp_qoriq: make p... |
188 |
EXPORT_SYMBOL_GPL(ptp_qoriq_adjfine); |
c78275f36 ptp: Added a cloc... |
189 |
|
73356e4ea ptp_qoriq: make p... |
190 |
int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta) |
c78275f36 ptp: Added a cloc... |
191 192 193 |
{ s64 now; unsigned long flags; |
1e562c815 ptp_qoriq: make s... |
194 |
struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps); |
c78275f36 ptp: Added a cloc... |
195 |
|
1e562c815 ptp_qoriq: make s... |
196 |
spin_lock_irqsave(&ptp_qoriq->lock, flags); |
c78275f36 ptp: Added a cloc... |
197 |
|
1e562c815 ptp_qoriq: make s... |
198 |
now = tmr_cnt_read(ptp_qoriq); |
c78275f36 ptp: Added a cloc... |
199 |
now += delta; |
1e562c815 ptp_qoriq: make s... |
200 201 |
tmr_cnt_write(ptp_qoriq, now); set_fipers(ptp_qoriq); |
c78275f36 ptp: Added a cloc... |
202 |
|
1e562c815 ptp_qoriq: make s... |
203 |
spin_unlock_irqrestore(&ptp_qoriq->lock, flags); |
c78275f36 ptp: Added a cloc... |
204 |
|
c78275f36 ptp: Added a cloc... |
205 206 |
return 0; } |
73356e4ea ptp_qoriq: make p... |
207 |
EXPORT_SYMBOL_GPL(ptp_qoriq_adjtime); |
c78275f36 ptp: Added a cloc... |
208 |
|
73356e4ea ptp_qoriq: make p... |
209 |
int ptp_qoriq_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) |
c78275f36 ptp: Added a cloc... |
210 211 |
{ u64 ns; |
c78275f36 ptp: Added a cloc... |
212 |
unsigned long flags; |
1e562c815 ptp_qoriq: make s... |
213 |
struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps); |
c78275f36 ptp: Added a cloc... |
214 |
|
1e562c815 ptp_qoriq: make s... |
215 |
spin_lock_irqsave(&ptp_qoriq->lock, flags); |
c78275f36 ptp: Added a cloc... |
216 |
|
1e562c815 ptp_qoriq: make s... |
217 |
ns = tmr_cnt_read(ptp_qoriq); |
c78275f36 ptp: Added a cloc... |
218 |
|
1e562c815 ptp_qoriq: make s... |
219 |
spin_unlock_irqrestore(&ptp_qoriq->lock, flags); |
c78275f36 ptp: Added a cloc... |
220 |
|
3359e7c2e ptp: gianfar: use... |
221 |
*ts = ns_to_timespec64(ns); |
c78275f36 ptp: Added a cloc... |
222 223 |
return 0; } |
73356e4ea ptp_qoriq: make p... |
224 |
EXPORT_SYMBOL_GPL(ptp_qoriq_gettime); |
c78275f36 ptp: Added a cloc... |
225 |
|
73356e4ea ptp_qoriq: make p... |
226 227 |
int ptp_qoriq_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) |
c78275f36 ptp: Added a cloc... |
228 229 230 |
{ u64 ns; unsigned long flags; |
1e562c815 ptp_qoriq: make s... |
231 |
struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps); |
c78275f36 ptp: Added a cloc... |
232 |
|
3359e7c2e ptp: gianfar: use... |
233 |
ns = timespec64_to_ns(ts); |
c78275f36 ptp: Added a cloc... |
234 |
|
1e562c815 ptp_qoriq: make s... |
235 |
spin_lock_irqsave(&ptp_qoriq->lock, flags); |
c78275f36 ptp: Added a cloc... |
236 |
|
1e562c815 ptp_qoriq: make s... |
237 238 |
tmr_cnt_write(ptp_qoriq, ns); set_fipers(ptp_qoriq); |
c78275f36 ptp: Added a cloc... |
239 |
|
1e562c815 ptp_qoriq: make s... |
240 |
spin_unlock_irqrestore(&ptp_qoriq->lock, flags); |
c78275f36 ptp: Added a cloc... |
241 242 243 |
return 0; } |
73356e4ea ptp_qoriq: make p... |
244 |
EXPORT_SYMBOL_GPL(ptp_qoriq_settime); |
c78275f36 ptp: Added a cloc... |
245 |
|
73356e4ea ptp_qoriq: make p... |
246 247 |
int ptp_qoriq_enable(struct ptp_clock_info *ptp, struct ptp_clock_request *rq, int on) |
c78275f36 ptp: Added a cloc... |
248 |
{ |
1e562c815 ptp_qoriq: make s... |
249 250 |
struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps); struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; |
c78275f36 ptp: Added a cloc... |
251 |
unsigned long flags; |
b0bc10cc8 ptp_qoriq: fix in... |
252 |
u32 bit, mask = 0; |
c78275f36 ptp: Added a cloc... |
253 254 255 256 257 258 259 260 261 262 263 264 265 |
switch (rq->type) { case PTP_CLK_REQ_EXTTS: switch (rq->extts.index) { case 0: bit = ETS1EN; break; case 1: bit = ETS2EN; break; default: return -EINVAL; } |
6815d8b09 ptp_qoriq: suppor... |
266 267 |
if (on) |
1e562c815 ptp_qoriq: make s... |
268 |
extts_clean_up(ptp_qoriq, rq->extts.index, false); |
6815d8b09 ptp_qoriq: suppor... |
269 |
|
b0bc10cc8 ptp_qoriq: fix in... |
270 |
break; |
c78275f36 ptp: Added a cloc... |
271 |
case PTP_CLK_REQ_PPS: |
b0bc10cc8 ptp_qoriq: fix in... |
272 |
bit = PP1EN; |
c78275f36 ptp: Added a cloc... |
273 |
break; |
b0bc10cc8 ptp_qoriq: fix in... |
274 275 276 |
default: return -EOPNOTSUPP; } |
1e562c815 ptp_qoriq: make s... |
277 |
spin_lock_irqsave(&ptp_qoriq->lock, flags); |
b0bc10cc8 ptp_qoriq: fix in... |
278 |
|
f038ddf25 ptp_qoriq: add li... |
279 |
mask = ptp_qoriq->read(®s->ctrl_regs->tmr_temask); |
b0bc10cc8 ptp_qoriq: fix in... |
280 281 |
if (on) { mask |= bit; |
f038ddf25 ptp_qoriq: add li... |
282 |
ptp_qoriq->write(®s->ctrl_regs->tmr_tevent, bit); |
b0bc10cc8 ptp_qoriq: fix in... |
283 284 |
} else { mask &= ~bit; |
c78275f36 ptp: Added a cloc... |
285 |
} |
f038ddf25 ptp_qoriq: add li... |
286 |
ptp_qoriq->write(®s->ctrl_regs->tmr_temask, mask); |
b0bc10cc8 ptp_qoriq: fix in... |
287 |
|
1e562c815 ptp_qoriq: make s... |
288 |
spin_unlock_irqrestore(&ptp_qoriq->lock, flags); |
b0bc10cc8 ptp_qoriq: fix in... |
289 |
return 0; |
c78275f36 ptp: Added a cloc... |
290 |
} |
73356e4ea ptp_qoriq: make p... |
291 |
EXPORT_SYMBOL_GPL(ptp_qoriq_enable); |
c78275f36 ptp: Added a cloc... |
292 |
|
ceefc71d4 ptp: rework gianf... |
293 |
static const struct ptp_clock_info ptp_qoriq_caps = { |
c78275f36 ptp: Added a cloc... |
294 |
.owner = THIS_MODULE, |
ceefc71d4 ptp: rework gianf... |
295 |
.name = "qoriq ptp clock", |
c78275f36 ptp: Added a cloc... |
296 |
.max_adj = 512000, |
cd4baaaa0 gianfar: do not a... |
297 |
.n_alarm = 0, |
c78275f36 ptp: Added a cloc... |
298 299 |
.n_ext_ts = N_EXT_TS, .n_per_out = 0, |
4986b4f00 ptp: drivers: set... |
300 |
.n_pins = 0, |
c78275f36 ptp: Added a cloc... |
301 |
.pps = 1, |
ceefc71d4 ptp: rework gianf... |
302 303 304 305 306 |
.adjfine = ptp_qoriq_adjfine, .adjtime = ptp_qoriq_adjtime, .gettime64 = ptp_qoriq_gettime, .settime64 = ptp_qoriq_settime, .enable = ptp_qoriq_enable, |
c78275f36 ptp: Added a cloc... |
307 |
}; |
91305f281 ptp_qoriq: suppor... |
308 |
/** |
1e562c815 ptp_qoriq: make s... |
309 |
* ptp_qoriq_nominal_freq - calculate nominal frequency according to |
91305f281 ptp_qoriq: suppor... |
310 311 312 313 314 315 316 317 318 319 |
* reference clock frequency * * @clk_src: reference clock frequency * * The nominal frequency is the desired clock frequency. * It should be less than the reference clock frequency. * It should be a factor of 1000MHz. * * Return the nominal frequency */ |
1e562c815 ptp_qoriq: make s... |
320 |
static u32 ptp_qoriq_nominal_freq(u32 clk_src) |
91305f281 ptp_qoriq: suppor... |
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
{ u32 remainder = 0; clk_src /= 1000000; remainder = clk_src % 100; if (remainder) { clk_src -= remainder; clk_src += 100; } do { clk_src -= 100; } while (1000 % clk_src); return clk_src * 1000000; } /** |
1e562c815 ptp_qoriq: make s... |
340 |
* ptp_qoriq_auto_config - calculate a set of default configurations |
91305f281 ptp_qoriq: suppor... |
341 |
* |
1e562c815 ptp_qoriq: make s... |
342 |
* @ptp_qoriq: pointer to ptp_qoriq |
91305f281 ptp_qoriq: suppor... |
343 344 345 346 347 348 349 350 351 |
* @node: pointer to device_node * * If below dts properties are not provided, this function will be * called to calculate a set of default configurations for them. * "fsl,tclk-period" * "fsl,tmr-prsc" * "fsl,tmr-add" * "fsl,tmr-fiper1" * "fsl,tmr-fiper2" |
6d23d831e ptp_qoriq: suppor... |
352 |
* "fsl,tmr-fiper3" (required only for DPAA2 and ENETC hardware) |
91305f281 ptp_qoriq: suppor... |
353 354 355 356 |
* "fsl,max-adj" * * Return 0 if success */ |
1e562c815 ptp_qoriq: make s... |
357 |
static int ptp_qoriq_auto_config(struct ptp_qoriq *ptp_qoriq, |
91305f281 ptp_qoriq: suppor... |
358 359 360 361 362 363 |
struct device_node *node) { struct clk *clk; u64 freq_comp; u64 max_adj; u32 nominal_freq; |
74c05a33c ptp_qoriq: use di... |
364 |
u32 remainder = 0; |
91305f281 ptp_qoriq: suppor... |
365 |
u32 clk_src = 0; |
1e562c815 ptp_qoriq: make s... |
366 |
ptp_qoriq->cksel = DEFAULT_CKSEL; |
91305f281 ptp_qoriq: suppor... |
367 368 369 370 371 372 373 374 375 376 377 378 |
clk = of_clk_get(node, 0); if (!IS_ERR(clk)) { clk_src = clk_get_rate(clk); clk_put(clk); } if (clk_src <= 100000000UL) { pr_err("error reference clock value, or lower than 100MHz "); return -EINVAL; } |
1e562c815 ptp_qoriq: make s... |
379 |
nominal_freq = ptp_qoriq_nominal_freq(clk_src); |
91305f281 ptp_qoriq: suppor... |
380 381 |
if (!nominal_freq) return -EINVAL; |
1e562c815 ptp_qoriq: make s... |
382 383 |
ptp_qoriq->tclk_period = 1000000000UL / nominal_freq; ptp_qoriq->tmr_prsc = DEFAULT_TMR_PRSC; |
91305f281 ptp_qoriq: suppor... |
384 385 386 387 388 389 |
/* Calculate initial frequency compensation value for TMR_ADD register. * freq_comp = ceil(2^32 / freq_ratio) * freq_ratio = reference_clock_freq / nominal_freq */ freq_comp = ((u64)1 << 32) * nominal_freq; |
74c05a33c ptp_qoriq: use di... |
390 391 |
freq_comp = div_u64_rem(freq_comp, clk_src, &remainder); if (remainder) |
91305f281 ptp_qoriq: suppor... |
392 |
freq_comp++; |
1e562c815 ptp_qoriq: make s... |
393 394 395 |
ptp_qoriq->tmr_add = freq_comp; ptp_qoriq->tmr_fiper1 = DEFAULT_FIPER1_PERIOD - ptp_qoriq->tclk_period; ptp_qoriq->tmr_fiper2 = DEFAULT_FIPER2_PERIOD - ptp_qoriq->tclk_period; |
6d23d831e ptp_qoriq: suppor... |
396 |
ptp_qoriq->tmr_fiper3 = DEFAULT_FIPER3_PERIOD - ptp_qoriq->tclk_period; |
91305f281 ptp_qoriq: suppor... |
397 398 399 400 401 |
/* max_adj = 1000000000 * (freq_ratio - 1.0) - 1 * freq_ratio = reference_clock_freq / nominal_freq */ max_adj = 1000000000ULL * (clk_src - nominal_freq); |
74c05a33c ptp_qoriq: use di... |
402 |
max_adj = div_u64(max_adj, nominal_freq) - 1; |
1e562c815 ptp_qoriq: make s... |
403 |
ptp_qoriq->caps.max_adj = max_adj; |
91305f281 ptp_qoriq: suppor... |
404 405 406 |
return 0; } |
ff54571a7 ptp_qoriq: conver... |
407 |
int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base, |
58066ac9d ptp_qoriq: don't ... |
408 |
const struct ptp_clock_info *caps) |
c78275f36 ptp: Added a cloc... |
409 |
{ |
ff54571a7 ptp_qoriq: conver... |
410 |
struct device_node *node = ptp_qoriq->dev->of_node; |
1e562c815 ptp_qoriq: make s... |
411 |
struct ptp_qoriq_registers *regs; |
d28fdf0fe ptp: gianfar: con... |
412 |
struct timespec64 now; |
c78275f36 ptp: Added a cloc... |
413 |
unsigned long flags; |
ff54571a7 ptp_qoriq: conver... |
414 |
u32 tmr_ctrl; |
c78275f36 ptp: Added a cloc... |
415 |
|
7f4399ba4 ptp_qoriq: fix NU... |
416 417 |
if (!node) return -ENODEV; |
ff54571a7 ptp_qoriq: conver... |
418 |
ptp_qoriq->base = base; |
58066ac9d ptp_qoriq: don't ... |
419 |
ptp_qoriq->caps = *caps; |
e58f6f4fb powerpc/83xx: gia... |
420 |
|
1e562c815 ptp_qoriq: make s... |
421 422 |
if (of_property_read_u32(node, "fsl,cksel", &ptp_qoriq->cksel)) ptp_qoriq->cksel = DEFAULT_CKSEL; |
c78275f36 ptp: Added a cloc... |
423 |
|
6815d8b09 ptp_qoriq: suppor... |
424 |
if (of_property_read_bool(node, "fsl,extts-fifo")) |
1e562c815 ptp_qoriq: make s... |
425 |
ptp_qoriq->extts_fifo_support = true; |
6815d8b09 ptp_qoriq: suppor... |
426 |
else |
1e562c815 ptp_qoriq: make s... |
427 |
ptp_qoriq->extts_fifo_support = false; |
6815d8b09 ptp_qoriq: suppor... |
428 |
|
6d23d831e ptp_qoriq: suppor... |
429 430 431 |
if (of_device_is_compatible(node, "fsl,dpaa2-ptp") || of_device_is_compatible(node, "fsl,enetc-ptp")) ptp_qoriq->fiper3_support = true; |
c35ec7796 gianfar_ptp: repl... |
432 |
if (of_property_read_u32(node, |
1e562c815 ptp_qoriq: make s... |
433 |
"fsl,tclk-period", &ptp_qoriq->tclk_period) || |
c35ec7796 gianfar_ptp: repl... |
434 |
of_property_read_u32(node, |
1e562c815 ptp_qoriq: make s... |
435 |
"fsl,tmr-prsc", &ptp_qoriq->tmr_prsc) || |
c35ec7796 gianfar_ptp: repl... |
436 |
of_property_read_u32(node, |
1e562c815 ptp_qoriq: make s... |
437 |
"fsl,tmr-add", &ptp_qoriq->tmr_add) || |
c35ec7796 gianfar_ptp: repl... |
438 |
of_property_read_u32(node, |
1e562c815 ptp_qoriq: make s... |
439 |
"fsl,tmr-fiper1", &ptp_qoriq->tmr_fiper1) || |
c35ec7796 gianfar_ptp: repl... |
440 |
of_property_read_u32(node, |
1e562c815 ptp_qoriq: make s... |
441 |
"fsl,tmr-fiper2", &ptp_qoriq->tmr_fiper2) || |
c35ec7796 gianfar_ptp: repl... |
442 |
of_property_read_u32(node, |
6d23d831e ptp_qoriq: suppor... |
443 444 445 446 |
"fsl,max-adj", &ptp_qoriq->caps.max_adj) || (ptp_qoriq->fiper3_support && of_property_read_u32(node, "fsl,tmr-fiper3", &ptp_qoriq->tmr_fiper3))) { |
91305f281 ptp_qoriq: suppor... |
447 448 |
pr_warn("device tree node missing required elements, try automatic configuration "); |
1e562c815 ptp_qoriq: make s... |
449 |
if (ptp_qoriq_auto_config(ptp_qoriq, node)) |
ff54571a7 ptp_qoriq: conver... |
450 |
return -ENODEV; |
c78275f36 ptp: Added a cloc... |
451 |
} |
f038ddf25 ptp_qoriq: add li... |
452 453 454 455 456 457 458 |
if (of_property_read_bool(node, "little-endian")) { ptp_qoriq->read = qoriq_read_le; ptp_qoriq->write = qoriq_write_le; } else { ptp_qoriq->read = qoriq_read_be; ptp_qoriq->write = qoriq_write_be; } |
d4e176870 ptp_qoriq: fix re... |
459 460 461 462 463 464 |
/* The eTSEC uses differnt memory map with DPAA/ENETC */ if (of_device_is_compatible(node, "fsl,etsec-ptp")) { ptp_qoriq->regs.ctrl_regs = base + ETSEC_CTRL_REGS_OFFSET; ptp_qoriq->regs.alarm_regs = base + ETSEC_ALARM_REGS_OFFSET; ptp_qoriq->regs.fiper_regs = base + ETSEC_FIPER_REGS_OFFSET; ptp_qoriq->regs.etts_regs = base + ETSEC_ETTS_REGS_OFFSET; |
a8f62d0c6 ptp: support DPAA... |
465 |
} else { |
1e562c815 ptp_qoriq: make s... |
466 467 468 469 |
ptp_qoriq->regs.ctrl_regs = base + CTRL_REGS_OFFSET; ptp_qoriq->regs.alarm_regs = base + ALARM_REGS_OFFSET; ptp_qoriq->regs.fiper_regs = base + FIPER_REGS_OFFSET; ptp_qoriq->regs.etts_regs = base + ETTS_REGS_OFFSET; |
a8f62d0c6 ptp: support DPAA... |
470 |
} |
db34a4714 ptp_qoriq: Initia... |
471 |
spin_lock_init(&ptp_qoriq->lock); |
f696a21c2 ptp: replace getn... |
472 |
ktime_get_real_ts64(&now); |
1e562c815 ptp_qoriq: make s... |
473 |
ptp_qoriq_settime(&ptp_qoriq->caps, &now); |
c78275f36 ptp: Added a cloc... |
474 475 |
tmr_ctrl = |
1e562c815 ptp_qoriq: make s... |
476 477 |
(ptp_qoriq->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT | (ptp_qoriq->cksel & CKSEL_MASK) << CKSEL_SHIFT; |
c78275f36 ptp: Added a cloc... |
478 |
|
1e562c815 ptp_qoriq: make s... |
479 |
spin_lock_irqsave(&ptp_qoriq->lock, flags); |
c78275f36 ptp: Added a cloc... |
480 |
|
1e562c815 ptp_qoriq: make s... |
481 |
regs = &ptp_qoriq->regs; |
f038ddf25 ptp_qoriq: add li... |
482 483 484 485 486 |
ptp_qoriq->write(®s->ctrl_regs->tmr_ctrl, tmr_ctrl); ptp_qoriq->write(®s->ctrl_regs->tmr_add, ptp_qoriq->tmr_add); ptp_qoriq->write(®s->ctrl_regs->tmr_prsc, ptp_qoriq->tmr_prsc); ptp_qoriq->write(®s->fiper_regs->tmr_fiper1, ptp_qoriq->tmr_fiper1); ptp_qoriq->write(®s->fiper_regs->tmr_fiper2, ptp_qoriq->tmr_fiper2); |
6d23d831e ptp_qoriq: suppor... |
487 488 489 490 |
if (ptp_qoriq->fiper3_support) ptp_qoriq->write(®s->fiper_regs->tmr_fiper3, ptp_qoriq->tmr_fiper3); |
1e562c815 ptp_qoriq: make s... |
491 |
set_alarm(ptp_qoriq); |
f038ddf25 ptp_qoriq: add li... |
492 493 |
ptp_qoriq->write(®s->ctrl_regs->tmr_ctrl, tmr_ctrl|FIPERST|RTPE|TE|FRD); |
c78275f36 ptp: Added a cloc... |
494 |
|
1e562c815 ptp_qoriq: make s... |
495 |
spin_unlock_irqrestore(&ptp_qoriq->lock, flags); |
c78275f36 ptp: Added a cloc... |
496 |
|
ff54571a7 ptp_qoriq: conver... |
497 498 499 |
ptp_qoriq->clock = ptp_clock_register(&ptp_qoriq->caps, ptp_qoriq->dev); if (IS_ERR(ptp_qoriq->clock)) return PTR_ERR(ptp_qoriq->clock); |
c78275f36 ptp: Added a cloc... |
500 |
|
ff54571a7 ptp_qoriq: conver... |
501 |
ptp_qoriq->phc_index = ptp_clock_index(ptp_qoriq->clock); |
1e562c815 ptp_qoriq: make s... |
502 |
ptp_qoriq_create_debugfs(ptp_qoriq); |
ff54571a7 ptp_qoriq: conver... |
503 504 505 506 507 508 509 |
return 0; } EXPORT_SYMBOL_GPL(ptp_qoriq_init); void ptp_qoriq_free(struct ptp_qoriq *ptp_qoriq) { struct ptp_qoriq_registers *regs = &ptp_qoriq->regs; |
f038ddf25 ptp_qoriq: add li... |
510 511 |
ptp_qoriq->write(®s->ctrl_regs->tmr_temask, 0); ptp_qoriq->write(®s->ctrl_regs->tmr_ctrl, 0); |
ff54571a7 ptp_qoriq: conver... |
512 513 514 515 516 517 518 519 520 521 522 523 524 |
ptp_qoriq_remove_debugfs(ptp_qoriq); ptp_clock_unregister(ptp_qoriq->clock); iounmap(ptp_qoriq->base); free_irq(ptp_qoriq->irq, ptp_qoriq); } EXPORT_SYMBOL_GPL(ptp_qoriq_free); static int ptp_qoriq_probe(struct platform_device *dev) { struct ptp_qoriq *ptp_qoriq; int err = -ENOMEM; void __iomem *base; |
c78275f36 ptp: Added a cloc... |
525 |
|
ff54571a7 ptp_qoriq: conver... |
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 |
ptp_qoriq = kzalloc(sizeof(*ptp_qoriq), GFP_KERNEL); if (!ptp_qoriq) goto no_memory; ptp_qoriq->dev = &dev->dev; err = -ENODEV; ptp_qoriq->irq = platform_get_irq(dev, 0); if (ptp_qoriq->irq < 0) { pr_err("irq not in device tree "); goto no_node; } if (request_irq(ptp_qoriq->irq, ptp_qoriq_isr, IRQF_SHARED, DRIVER, ptp_qoriq)) { pr_err("request_irq failed "); goto no_node; } ptp_qoriq->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0); if (!ptp_qoriq->rsrc) { pr_err("no resource "); goto no_resource; } if (request_resource(&iomem_resource, ptp_qoriq->rsrc)) { pr_err("resource busy "); goto no_resource; } base = ioremap(ptp_qoriq->rsrc->start, resource_size(ptp_qoriq->rsrc)); if (!base) { pr_err("ioremap ptp registers failed "); goto no_ioremap; } |
58066ac9d ptp_qoriq: don't ... |
566 |
err = ptp_qoriq_init(ptp_qoriq, base, &ptp_qoriq_caps); |
ff54571a7 ptp_qoriq: conver... |
567 568 569 570 |
if (err) goto no_clock; platform_set_drvdata(dev, ptp_qoriq); |
c78275f36 ptp: Added a cloc... |
571 572 573 |
return 0; no_clock: |
1e562c815 ptp_qoriq: make s... |
574 |
iounmap(ptp_qoriq->base); |
c78275f36 ptp: Added a cloc... |
575 |
no_ioremap: |
1e562c815 ptp_qoriq: make s... |
576 |
release_resource(ptp_qoriq->rsrc); |
c78275f36 ptp: Added a cloc... |
577 |
no_resource: |
1e562c815 ptp_qoriq: make s... |
578 |
free_irq(ptp_qoriq->irq, ptp_qoriq); |
c78275f36 ptp: Added a cloc... |
579 |
no_node: |
1e562c815 ptp_qoriq: make s... |
580 |
kfree(ptp_qoriq); |
c78275f36 ptp: Added a cloc... |
581 582 583 |
no_memory: return err; } |
1e562c815 ptp_qoriq: make s... |
584 |
static int ptp_qoriq_remove(struct platform_device *dev) |
c78275f36 ptp: Added a cloc... |
585 |
{ |
1e562c815 ptp_qoriq: make s... |
586 |
struct ptp_qoriq *ptp_qoriq = platform_get_drvdata(dev); |
c78275f36 ptp: Added a cloc... |
587 |
|
ff54571a7 ptp_qoriq: conver... |
588 |
ptp_qoriq_free(ptp_qoriq); |
1e562c815 ptp_qoriq: make s... |
589 |
release_resource(ptp_qoriq->rsrc); |
1e562c815 ptp_qoriq: make s... |
590 |
kfree(ptp_qoriq); |
c78275f36 ptp: Added a cloc... |
591 592 |
return 0; } |
94e5a2a88 net/fsl: constify... |
593 |
static const struct of_device_id match_table[] = { |
c78275f36 ptp: Added a cloc... |
594 |
{ .compatible = "fsl,etsec-ptp" }, |
a8f62d0c6 ptp: support DPAA... |
595 |
{ .compatible = "fsl,fman-ptp-timer" }, |
c78275f36 ptp: Added a cloc... |
596 597 |
{}, }; |
238600637 net: gianfar_ptp:... |
598 |
MODULE_DEVICE_TABLE(of, match_table); |
c78275f36 ptp: Added a cloc... |
599 |
|
1e562c815 ptp_qoriq: make s... |
600 |
static struct platform_driver ptp_qoriq_driver = { |
c78275f36 ptp: Added a cloc... |
601 |
.driver = { |
ceefc71d4 ptp: rework gianf... |
602 |
.name = "ptp_qoriq", |
c78275f36 ptp: Added a cloc... |
603 |
.of_match_table = match_table, |
c78275f36 ptp: Added a cloc... |
604 |
}, |
1e562c815 ptp_qoriq: make s... |
605 606 |
.probe = ptp_qoriq_probe, .remove = ptp_qoriq_remove, |
c78275f36 ptp: Added a cloc... |
607 |
}; |
1e562c815 ptp_qoriq: make s... |
608 |
module_platform_driver(ptp_qoriq_driver); |
c78275f36 ptp: Added a cloc... |
609 |
|
c2ec3ff6b phc: Update autho... |
610 |
MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>"); |
ceefc71d4 ptp: rework gianf... |
611 |
MODULE_DESCRIPTION("PTP clock for Freescale QorIQ 1588 timer"); |
c78275f36 ptp: Added a cloc... |
612 |
MODULE_LICENSE("GPL"); |