Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/arm/ti/am335x/am335x_dmtpps.c
39536 views
1
/*-
2
* Copyright (c) 2015 Ian lepore <[email protected]>
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
/*
28
* AM335x PPS driver using DMTimer capture.
29
*
30
* Note that this PPS driver does not use an interrupt. Instead it uses the
31
* hardware's ability to latch the timer's count register in response to a
32
* signal on an IO pin. Each of timers 4-7 have an associated pin, and this
33
* code allows any one of those to be used.
34
*
35
* The timecounter routines in kern_tc.c call the pps poll routine periodically
36
* to see if a new counter value has been latched. When a new value has been
37
* latched, the only processing done in the poll routine is to capture the
38
* current set of timecounter timehands (done with pps_capture()) and the
39
* latched value from the timer. The remaining work (done by pps_event() while
40
* holding a mutex) is scheduled to be done later in a non-interrupt context.
41
*/
42
43
#include <sys/cdefs.h>
44
#include "opt_platform.h"
45
46
#include <sys/param.h>
47
#include <sys/systm.h>
48
#include <sys/bus.h>
49
#include <sys/conf.h>
50
#include <sys/kernel.h>
51
#include <sys/lock.h>
52
#include <sys/module.h>
53
#include <sys/malloc.h>
54
#include <sys/mutex.h>
55
#include <sys/rman.h>
56
#include <sys/timepps.h>
57
#include <sys/timetc.h>
58
#include <machine/bus.h>
59
60
#include <dev/ofw/openfirm.h>
61
#include <dev/ofw/ofw_bus.h>
62
#include <dev/ofw/ofw_bus_subr.h>
63
#include <dev/clk/clk.h>
64
65
#include <arm/ti/ti_sysc.h>
66
#include <arm/ti/ti_pinmux.h>
67
#include <arm/ti/am335x/am335x_scm_padconf.h>
68
69
#include "am335x_dmtreg.h"
70
71
#define PPS_CDEV_NAME "dmtpps"
72
73
struct dmtpps_softc {
74
device_t dev;
75
int mem_rid;
76
struct resource * mem_res;
77
int tmr_num; /* N from hwmod str "timerN" */
78
char tmr_name[12]; /* "DMTimerN" */
79
uint32_t tclr; /* Cached TCLR register. */
80
struct timecounter tc;
81
int pps_curmode; /* Edge mode now set in hw. */
82
struct cdev * pps_cdev;
83
struct pps_state pps_state;
84
struct mtx pps_mtx;
85
clk_t clk_fck;
86
uint64_t sysclk_freq;
87
};
88
89
static int dmtpps_tmr_num; /* Set by probe() */
90
91
/* List of compatible strings for FDT tree */
92
static struct ofw_compat_data compat_data[] = {
93
{"ti,am335x-timer", 1},
94
{"ti,am335x-timer-1ms", 1},
95
{NULL, 0},
96
};
97
SIMPLEBUS_PNP_INFO(compat_data);
98
99
/*
100
* A table relating pad names to the hardware timer number they can be mux'd to.
101
*/
102
struct padinfo {
103
char * ballname;
104
int tmr_num;
105
};
106
static struct padinfo dmtpps_padinfo[] = {
107
{"GPMC_ADVn_ALE", 4},
108
{"I2C0_SDA", 4},
109
{"MII1_TX_EN", 4},
110
{"XDMA_EVENT_INTR0", 4},
111
{"GPMC_BEn0_CLE", 5},
112
{"MDC", 5},
113
{"MMC0_DAT3", 5},
114
{"UART1_RTSn", 5},
115
{"GPMC_WEn", 6},
116
{"MDIO", 6},
117
{"MMC0_DAT2", 6},
118
{"UART1_CTSn", 6},
119
{"GPMC_OEn_REn", 7},
120
{"I2C0_SCL", 7},
121
{"UART0_CTSn", 7},
122
{"XDMA_EVENT_INTR1", 7},
123
{NULL, 0}
124
};
125
126
/*
127
* This is either brilliantly user-friendly, or utterly lame...
128
*
129
* The am335x chip is used on the popular Beaglebone boards. Those boards have
130
* pins for all four capture-capable timers available on the P8 header. Allow
131
* users to configure the input pin by giving the name of the header pin.
132
*/
133
struct nicknames {
134
const char * nick;
135
const char * name;
136
};
137
static struct nicknames dmtpps_pin_nicks[] = {
138
{"P8-7", "GPMC_ADVn_ALE"},
139
{"P8-9", "GPMC_BEn0_CLE"},
140
{"P8-10", "GPMC_WEn"},
141
{"P8-8", "GPMC_OEn_REn",},
142
{NULL, NULL}
143
};
144
145
#define DMTIMER_READ4(sc, reg) bus_read_4((sc)->mem_res, (reg))
146
#define DMTIMER_WRITE4(sc, reg, val) bus_write_4((sc)->mem_res, (reg), (val))
147
148
/*
149
* Translate a short friendly case-insensitive name to its canonical name.
150
*/
151
static const char *
152
dmtpps_translate_nickname(const char *nick)
153
{
154
struct nicknames *nn;
155
156
for (nn = dmtpps_pin_nicks; nn->nick != NULL; nn++)
157
if (strcasecmp(nick, nn->nick) == 0)
158
return nn->name;
159
return (nick);
160
}
161
162
/*
163
* See if our tunable is set to the name of the input pin. If not, that's NOT
164
* an error, return 0. If so, try to configure that pin as a timer capture
165
* input pin, and if that works, then we have our timer unit number and if it
166
* fails that IS an error, return -1.
167
*/
168
static int
169
dmtpps_find_tmr_num_by_tunable(void)
170
{
171
struct padinfo *pi;
172
char iname[20];
173
char muxmode[12];
174
const char * ballname;
175
int err;
176
177
if (!TUNABLE_STR_FETCH("hw.am335x_dmtpps.input", iname, sizeof(iname)))
178
return (0);
179
ballname = dmtpps_translate_nickname(iname);
180
for (pi = dmtpps_padinfo; pi->ballname != NULL; pi++) {
181
if (strcmp(ballname, pi->ballname) != 0)
182
continue;
183
snprintf(muxmode, sizeof(muxmode), "timer%d", pi->tmr_num);
184
err = ti_pinmux_padconf_set(pi->ballname, muxmode,
185
PADCONF_INPUT);
186
if (err != 0) {
187
printf("am335x_dmtpps: unable to configure capture pin "
188
"for %s to input mode\n", muxmode);
189
return (-1);
190
} else if (bootverbose) {
191
printf("am335x_dmtpps: configured pin %s as input "
192
"for %s\n", iname, muxmode);
193
}
194
return (pi->tmr_num);
195
}
196
197
/* Invalid name in the tunable, that's an error. */
198
printf("am335x_dmtpps: unknown pin name '%s'\n", iname);
199
return (-1);
200
}
201
202
/*
203
* Ask the pinmux driver whether any pin has been configured as a TIMER4..TIMER7
204
* input pin. If so, return the timer number, if not return 0.
205
*/
206
static int
207
dmtpps_find_tmr_num_by_padconf(void)
208
{
209
int err;
210
unsigned int padstate;
211
const char * padmux;
212
struct padinfo *pi;
213
char muxmode[12];
214
215
for (pi = dmtpps_padinfo; pi->ballname != NULL; pi++) {
216
err = ti_pinmux_padconf_get(pi->ballname, &padmux, &padstate);
217
snprintf(muxmode, sizeof(muxmode), "timer%d", pi->tmr_num);
218
if (err == 0 && (padstate & RXACTIVE) != 0 &&
219
strcmp(muxmode, padmux) == 0)
220
return (pi->tmr_num);
221
}
222
/* Nothing found, not an error. */
223
return (0);
224
}
225
226
/*
227
* Figure out which hardware timer number to use based on input pin
228
* configuration. This is done just once, the first time probe() runs.
229
*/
230
static int
231
dmtpps_find_tmr_num(void)
232
{
233
int tmr_num;
234
235
if ((tmr_num = dmtpps_find_tmr_num_by_tunable()) == 0)
236
tmr_num = dmtpps_find_tmr_num_by_padconf();
237
238
if (tmr_num <= 0) {
239
printf("am335x_dmtpps: PPS driver not enabled: unable to find "
240
"or configure a capture input pin\n");
241
tmr_num = -1; /* Must return non-zero to prevent re-probing. */
242
}
243
return (tmr_num);
244
}
245
246
static void
247
dmtpps_set_hw_capture(struct dmtpps_softc *sc, bool force_off)
248
{
249
int newmode;
250
251
if (force_off)
252
newmode = 0;
253
else
254
newmode = sc->pps_state.ppsparam.mode & PPS_CAPTUREASSERT;
255
256
if (newmode == sc->pps_curmode)
257
return;
258
sc->pps_curmode = newmode;
259
260
if (newmode == PPS_CAPTUREASSERT)
261
sc->tclr |= DMT_TCLR_CAPTRAN_LOHI;
262
else
263
sc->tclr &= ~DMT_TCLR_CAPTRAN_MASK;
264
DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
265
}
266
267
static unsigned
268
dmtpps_get_timecount(struct timecounter *tc)
269
{
270
struct dmtpps_softc *sc;
271
272
sc = tc->tc_priv;
273
274
return (DMTIMER_READ4(sc, DMT_TCRR));
275
}
276
277
static void
278
dmtpps_poll(struct timecounter *tc)
279
{
280
struct dmtpps_softc *sc;
281
282
sc = tc->tc_priv;
283
284
/*
285
* If a new value has been latched we've got a PPS event. Capture the
286
* timecounter data, then override the capcount field (pps_capture()
287
* populates it from the current DMT_TCRR register) with the latched
288
* value from the TCAR1 register.
289
*
290
* Note that we don't have the TCAR interrupt enabled, but the hardware
291
* still provides the status bits in the "RAW" status register even when
292
* they're masked from generating an irq. However, when clearing the
293
* TCAR status to re-arm the capture for the next second, we have to
294
* write to the IRQ status register, not the RAW register. Quirky.
295
*
296
* We do not need to hold a lock while capturing the pps data, because
297
* it is captured into an area of the pps_state struct which is read
298
* only by pps_event(). We do need to hold a lock while calling
299
* pps_event(), because it manipulates data which is also accessed from
300
* the ioctl(2) context by userland processes.
301
*/
302
if (DMTIMER_READ4(sc, DMT_IRQSTATUS_RAW) & DMT_IRQ_TCAR) {
303
pps_capture(&sc->pps_state);
304
sc->pps_state.capcount = DMTIMER_READ4(sc, DMT_TCAR1);
305
DMTIMER_WRITE4(sc, DMT_IRQSTATUS, DMT_IRQ_TCAR);
306
307
mtx_lock_spin(&sc->pps_mtx);
308
pps_event(&sc->pps_state, PPS_CAPTUREASSERT);
309
mtx_unlock_spin(&sc->pps_mtx);
310
}
311
}
312
313
static int
314
dmtpps_open(struct cdev *dev, int flags, int fmt,
315
struct thread *td)
316
{
317
struct dmtpps_softc *sc;
318
319
sc = dev->si_drv1;
320
321
/*
322
* Begin polling for pps and enable capture in the hardware whenever the
323
* device is open. Doing this stuff again is harmless if this isn't the
324
* first open.
325
*/
326
sc->tc.tc_poll_pps = dmtpps_poll;
327
dmtpps_set_hw_capture(sc, false);
328
329
return 0;
330
}
331
332
static int
333
dmtpps_close(struct cdev *dev, int flags, int fmt,
334
struct thread *td)
335
{
336
struct dmtpps_softc *sc;
337
338
sc = dev->si_drv1;
339
340
/*
341
* Stop polling and disable capture on last close. Use the force-off
342
* flag to override the configured mode and turn off the hardware.
343
*/
344
sc->tc.tc_poll_pps = NULL;
345
dmtpps_set_hw_capture(sc, true);
346
347
return 0;
348
}
349
350
static int
351
dmtpps_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
352
int flags, struct thread *td)
353
{
354
struct dmtpps_softc *sc;
355
int err;
356
357
sc = dev->si_drv1;
358
359
/* Let the kernel do the heavy lifting for ioctl. */
360
mtx_lock_spin(&sc->pps_mtx);
361
err = pps_ioctl(cmd, data, &sc->pps_state);
362
mtx_unlock_spin(&sc->pps_mtx);
363
if (err != 0)
364
return (err);
365
366
/*
367
* The capture mode could have changed, set the hardware to whatever
368
* mode is now current. Effectively a no-op if nothing changed.
369
*/
370
dmtpps_set_hw_capture(sc, false);
371
372
return (err);
373
}
374
375
static struct cdevsw dmtpps_cdevsw = {
376
.d_version = D_VERSION,
377
.d_open = dmtpps_open,
378
.d_close = dmtpps_close,
379
.d_ioctl = dmtpps_ioctl,
380
.d_name = PPS_CDEV_NAME,
381
};
382
383
static int
384
dmtpps_probe(device_t dev)
385
{
386
int tmr_num;
387
uint64_t rev_address;
388
389
if (!ofw_bus_status_okay(dev))
390
return (ENXIO);
391
392
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
393
return (ENXIO);
394
395
/*
396
* If we haven't chosen which hardware timer to use yet, go do that now.
397
* We need to know that to decide whether to return success for this
398
* hardware timer instance or not.
399
*/
400
if (dmtpps_tmr_num == 0)
401
dmtpps_tmr_num = dmtpps_find_tmr_num();
402
403
/*
404
* Figure out which hardware timer is being probed and see if it matches
405
* the configured timer number determined earlier.
406
*/
407
rev_address = ti_sysc_get_rev_address(device_get_parent(dev));
408
switch (rev_address) {
409
case DMTIMER1_1MS_REV:
410
tmr_num = 1;
411
break;
412
case DMTIMER2_REV:
413
tmr_num = 2;
414
break;
415
case DMTIMER3_REV:
416
tmr_num = 3;
417
break;
418
case DMTIMER4_REV:
419
tmr_num = 4;
420
break;
421
case DMTIMER5_REV:
422
tmr_num = 5;
423
break;
424
case DMTIMER6_REV:
425
tmr_num = 6;
426
break;
427
case DMTIMER7_REV:
428
tmr_num = 7;
429
break;
430
default:
431
return (ENXIO);
432
}
433
434
if (dmtpps_tmr_num != tmr_num)
435
return (ENXIO);
436
437
device_set_descf(dev, "AM335x PPS-Capture DMTimer%d", tmr_num);
438
439
return(BUS_PROBE_DEFAULT);
440
}
441
442
static int
443
dmtpps_attach(device_t dev)
444
{
445
struct dmtpps_softc *sc;
446
struct make_dev_args mda;
447
int err;
448
clk_t sys_clkin;
449
uint64_t rev_address;
450
451
sc = device_get_softc(dev);
452
sc->dev = dev;
453
454
/* Figure out which hardware timer this is and set the name string. */
455
rev_address = ti_sysc_get_rev_address(device_get_parent(dev));
456
switch (rev_address) {
457
case DMTIMER1_1MS_REV:
458
sc->tmr_num = 1;
459
break;
460
case DMTIMER2_REV:
461
sc->tmr_num = 2;
462
break;
463
case DMTIMER3_REV:
464
sc->tmr_num = 3;
465
break;
466
case DMTIMER4_REV:
467
sc->tmr_num = 4;
468
break;
469
case DMTIMER5_REV:
470
sc->tmr_num = 5;
471
break;
472
case DMTIMER6_REV:
473
sc->tmr_num = 6;
474
break;
475
case DMTIMER7_REV:
476
sc->tmr_num = 7;
477
break;
478
}
479
snprintf(sc->tmr_name, sizeof(sc->tmr_name), "DMTimer%d", sc->tmr_num);
480
481
/* expect one clock */
482
err = clk_get_by_ofw_index(dev, 0, 0, &sc->clk_fck);
483
if (err != 0) {
484
device_printf(dev, "Cant find clock index 0. err: %d\n", err);
485
return (ENXIO);
486
}
487
488
err = clk_get_by_name(dev, "sys_clkin_ck@40", &sys_clkin);
489
if (err != 0) {
490
device_printf(dev, "Cant find sys_clkin_ck@40 err: %d\n", err);
491
return (ENXIO);
492
}
493
494
/* Select M_OSC as DPLL parent */
495
err = clk_set_parent_by_clk(sc->clk_fck, sys_clkin);
496
if (err != 0) {
497
device_printf(dev, "Cant set mux to CLK_M_OSC\n");
498
return (ENXIO);
499
}
500
501
/* Enable clocks and power on the device. */
502
err = ti_sysc_clock_enable(device_get_parent(dev));
503
if (err != 0) {
504
device_printf(dev, "Cant enable sysc clkctrl, err %d\n", err);
505
return (ENXIO);
506
}
507
508
/* Get the base clock frequency. */
509
err = clk_get_freq(sc->clk_fck, &sc->sysclk_freq);
510
if (err != 0) {
511
device_printf(dev, "Cant get sysclk frequency, err %d\n", err);
512
return (ENXIO);
513
}
514
/* Request the memory resources. */
515
sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
516
&sc->mem_rid, RF_ACTIVE);
517
if (sc->mem_res == NULL) {
518
return (ENXIO);
519
}
520
521
/*
522
* Configure the timer pulse/capture pin to input/capture mode. This is
523
* required in addition to configuring the pin as input with the pinmux
524
* controller (which was done via fdt data or tunable at probe time).
525
*/
526
sc->tclr = DMT_TCLR_GPO_CFG;
527
DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
528
529
/* Set up timecounter hardware, start it. */
530
DMTIMER_WRITE4(sc, DMT_TSICR, DMT_TSICR_RESET);
531
while (DMTIMER_READ4(sc, DMT_TIOCP_CFG) & DMT_TIOCP_RESET)
532
continue;
533
534
sc->tclr |= DMT_TCLR_START | DMT_TCLR_AUTOLOAD;
535
DMTIMER_WRITE4(sc, DMT_TLDR, 0);
536
DMTIMER_WRITE4(sc, DMT_TCRR, 0);
537
DMTIMER_WRITE4(sc, DMT_TCLR, sc->tclr);
538
539
/* Register the timecounter. */
540
sc->tc.tc_name = sc->tmr_name;
541
sc->tc.tc_get_timecount = dmtpps_get_timecount;
542
sc->tc.tc_counter_mask = ~0u;
543
sc->tc.tc_frequency = sc->sysclk_freq;
544
sc->tc.tc_quality = 1000;
545
sc->tc.tc_priv = sc;
546
547
tc_init(&sc->tc);
548
549
/*
550
* Indicate our PPS capabilities. Have the kernel init its part of the
551
* pps_state struct and add its capabilities.
552
*
553
* While the hardware has a mode to capture each edge, it's not clear we
554
* can use it that way, because there's only a single interrupt/status
555
* bit to say something was captured, but not which edge it was. For
556
* now, just say we can only capture assert events (the positive-going
557
* edge of the pulse).
558
*/
559
mtx_init(&sc->pps_mtx, "dmtpps", NULL, MTX_SPIN);
560
sc->pps_state.flags = PPSFLAG_MTX_SPIN;
561
sc->pps_state.ppscap = PPS_CAPTUREASSERT;
562
sc->pps_state.driver_abi = PPS_ABI_VERSION;
563
sc->pps_state.driver_mtx = &sc->pps_mtx;
564
pps_init_abi(&sc->pps_state);
565
566
/* Create the PPS cdev. */
567
make_dev_args_init(&mda);
568
mda.mda_flags = MAKEDEV_WAITOK;
569
mda.mda_devsw = &dmtpps_cdevsw;
570
mda.mda_cr = NULL;
571
mda.mda_uid = UID_ROOT;
572
mda.mda_gid = GID_WHEEL;
573
mda.mda_mode = 0600;
574
mda.mda_unit = device_get_unit(dev);
575
mda.mda_si_drv1 = sc;
576
if ((err = make_dev_s(&mda, &sc->pps_cdev, PPS_CDEV_NAME)) != 0) {
577
device_printf(dev, "Failed to create cdev %s\n", PPS_CDEV_NAME);
578
return (err);
579
}
580
581
if (bootverbose)
582
device_printf(sc->dev, "Using %s for PPS device /dev/%s\n",
583
sc->tmr_name, PPS_CDEV_NAME);
584
585
return (0);
586
}
587
588
static int
589
dmtpps_detach(device_t dev)
590
{
591
592
/*
593
* There is no way to remove a timecounter once it has been registered,
594
* even if it's not in use, so we can never detach. If we were
595
* dynamically loaded as a module this will prevent unloading.
596
*/
597
return (EBUSY);
598
}
599
600
static device_method_t dmtpps_methods[] = {
601
DEVMETHOD(device_probe, dmtpps_probe),
602
DEVMETHOD(device_attach, dmtpps_attach),
603
DEVMETHOD(device_detach, dmtpps_detach),
604
{ 0, 0 }
605
};
606
607
static driver_t dmtpps_driver = {
608
"am335x_dmtpps",
609
dmtpps_methods,
610
sizeof(struct dmtpps_softc),
611
};
612
613
DRIVER_MODULE(am335x_dmtpps, simplebus, dmtpps_driver, 0, 0);
614
MODULE_DEPEND(am335x_dmtpps, ti_sysc, 1, 1, 1);
615
616