1 /*-
2 * SPDX-License-Identifier: Beerware
3 *
4 * ----------------------------------------------------------------------------
5 * "THE BEER-WARE LICENSE" (Revision 42):
6 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
7 * can do whatever you want with this stuff. If we meet some day, and you think
8 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
9 * ----------------------------------------------------------------------------
10 *
11 *
12 * The AMD Elan sc520 is a system-on-chip gadget which is used in embedded
13 * kind of things, see www.soekris.com for instance, and it has a few quirks
14 * we need to deal with.
15 * Unfortunately we cannot identify the gadget by CPUID output because it
16 * depends on strapping options and only the stepping field may be useful
17 * and those are undocumented from AMDs side.
18 *
19 * So instead we recognize the on-chip host-PCI bridge and call back from
20 * sys/i386/pci/pci_bus.c to here if we find it.
21 *
22 * #ifdef CPU_ELAN_PPS
23 * The Elan has three general purpose counters, and when two of these
24 * are used just right they can hardware timestamp external events with
25 * approx 125 nsec resolution and +/- 125 nsec precision.
26 *
27 * Connect the signal to TMR1IN and a GPIO pin, and configure the GPIO pin
28 * with a 'P' in sysctl machdep.elan_gpio_config.
29 *
30 * The rising edge of the signal will start timer 1 counting up from
31 * zero, and when the timecounter polls for PPS, both counter 1 & 2 is
32 * read, as well as the GPIO bit. If a rising edge has happened, the
33 * contents of timer 1 which is how long time ago the edge happened,
34 * is subtracted from timer 2 to give us a "true time stamp".
35 *
36 * Echoing the PPS signal on any GPIO pin is supported (set it to 'e'
37 * or 'E' (inverted) in the sysctl) The echo signal should only be
38 * used as a visual indication, not for calibration since it suffers
39 * from 1/hz (or more) jitter which the timestamps are compensated for.
40 * #endif CPU_ELAN_PPS
41 */
42
43 #include <sys/cdefs.h>
44 __FBSDID("$FreeBSD$");
45
46 #include "opt_cpu.h"
47 #include <sys/param.h>
48 #include <sys/systm.h>
49 #include <sys/kernel.h>
50 #include <sys/conf.h>
51 #include <sys/sysctl.h>
52 #include <sys/syslog.h>
53 #include <sys/timetc.h>
54 #include <sys/proc.h>
55 #include <sys/uio.h>
56 #include <sys/lock.h>
57 #include <sys/mutex.h>
58 #include <sys/malloc.h>
59 #include <sys/sysctl.h>
60 #include <sys/timepps.h>
61 #include <sys/watchdog.h>
62
63 #include <dev/led/led.h>
64 #include <machine/md_var.h>
65 #include <machine/elan_mmcr.h>
66 #include <machine/pc/bios.h>
67
68 #include <vm/vm.h>
69 #include <vm/pmap.h>
70
71 static char gpio_config[33];
72
73 static volatile uint16_t *mmcrptr;
74 volatile struct elan_mmcr *elan_mmcr;
75
76 #ifdef CPU_ELAN_PPS
77 static struct pps_state elan_pps;
78 static volatile uint16_t *pps_ap[3];
79 static u_int pps_a, pps_d;
80 static u_int echo_a, echo_d;
81 #endif /* CPU_ELAN_PPS */
82
83 #ifdef CPU_SOEKRIS
84
85 static struct bios_oem bios_soekris = {
86 { 0xf0000, 0xf1000 },
87 {
88 { "Soekris", 0, 8 }, /* Soekris Engineering. */
89 { "net4", 0, 8 }, /* net45xx */
90 { "comBIOS", 0, 54 }, /* comBIOS ver. 1.26a 20040819 ... */
91 { NULL, 0, 0 },
92 }
93 };
94
95 #endif
96
97 static u_int led_cookie[32];
98 static struct cdev *led_dev[32];
99
100 static void
101 gpio_led(void *cookie, int state)
102 {
103 u_int u, v;
104
105 u = *(int *)cookie;
106 v = u & 0xffff;
107 u >>= 16;
108 if (!state)
109 v ^= 0xc;
110 mmcrptr[v / 2] = u;
111 }
112
113 static int
114 sysctl_machdep_elan_gpio_config(SYSCTL_HANDLER_ARGS)
115 {
116 u_int u, v;
117 int i, np, ne;
118 int error;
119 char buf[32];
120 char tmp[10];
121
122 error = SYSCTL_OUT(req, gpio_config, 33);
123 if (error != 0 || req->newptr == NULL)
124 return (error);
125 if (req->newlen != 32)
126 return (EINVAL);
127 error = SYSCTL_IN(req, buf, 32);
128 if (error != 0)
129 return (error);
130 /* Disallow any disabled pins and count pps and echo */
131 np = ne = 0;
132 for (i = 0; i < 32; i++) {
133 if (gpio_config[i] == '-' && buf[i] == '.')
134 buf[i] = gpio_config[i];
135 if (gpio_config[i] == '-' && buf[i] != '-')
136 return (EPERM);
137 if (buf[i] == 'P') {
138 np++;
139 if (np > 1)
140 return (EINVAL);
141 }
142 if (buf[i] == 'e' || buf[i] == 'E') {
143 ne++;
144 if (ne > 1)
145 return (EINVAL);
146 }
147 if (buf[i] != 'L' && buf[i] != 'l'
148 #ifdef CPU_ELAN_PPS
149 && buf[i] != 'P' && buf[i] != 'E' && buf[i] != 'e'
150 #endif /* CPU_ELAN_PPS */
151 && buf[i] != '.' && buf[i] != '-')
152 return (EINVAL);
153 }
154 #ifdef CPU_ELAN_PPS
155 if (np == 0)
156 pps_a = pps_d = 0;
157 if (ne == 0)
158 echo_a = echo_d = 0;
159 #endif
160 for (i = 0; i < 32; i++) {
161 u = 1 << (i & 0xf);
162 if (i >= 16)
163 v = 2;
164 else
165 v = 0;
166 #ifdef CPU_SOEKRIS
167 if (i == 9)
168 ;
169 else
170 #endif
171 if (buf[i] != 'l' && buf[i] != 'L' && led_dev[i] != NULL) {
172 led_destroy(led_dev[i]);
173 led_dev[i] = NULL;
174 mmcrptr[(0xc2a + v) / 2] &= ~u;
175 }
176 switch (buf[i]) {
177 #ifdef CPU_ELAN_PPS
178 case 'P':
179 pps_d = u;
180 pps_a = 0xc30 + v;
181 pps_ap[0] = &mmcrptr[pps_a / 2];
182 pps_ap[1] = &elan_mmcr->GPTMR2CNT;
183 pps_ap[2] = &elan_mmcr->GPTMR1CNT;
184 mmcrptr[(0xc2a + v) / 2] &= ~u;
185 gpio_config[i] = buf[i];
186 break;
187 case 'e':
188 case 'E':
189 echo_d = u;
190 if (buf[i] == 'E')
191 echo_a = 0xc34 + v;
192 else
193 echo_a = 0xc38 + v;
194 mmcrptr[(0xc2a + v) / 2] |= u;
195 gpio_config[i] = buf[i];
196 break;
197 #endif /* CPU_ELAN_PPS */
198 case 'l':
199 case 'L':
200 if (buf[i] == 'L')
201 led_cookie[i] = (0xc34 + v) | (u << 16);
202 else
203 led_cookie[i] = (0xc38 + v) | (u << 16);
204 if (led_dev[i])
205 break;
206 sprintf(tmp, "gpio%d", i);
207 mmcrptr[(0xc2a + v) / 2] |= u;
208 gpio_config[i] = buf[i];
209 led_dev[i] =
210 led_create(gpio_led, &led_cookie[i], tmp);
211 break;
212 case '.':
213 gpio_config[i] = buf[i];
214 break;
215 case '-':
216 default:
217 break;
218 }
219 }
220 return (0);
221 }
222
223 SYSCTL_OID(_machdep, OID_AUTO, elan_gpio_config, CTLTYPE_STRING | CTLFLAG_RW,
224 NULL, 0, sysctl_machdep_elan_gpio_config, "A", "Elan CPU GPIO pin config");
225
226 #ifdef CPU_ELAN_PPS
227 static void
228 elan_poll_pps(struct timecounter *tc)
229 {
230 static int state;
231 int i;
232 uint16_t u, x, y, z;
233 register_t saveintr;
234
235 /*
236 * Grab the HW state as quickly and compactly as we can. Disable
237 * interrupts to avoid measuring our interrupt service time on
238 * hw with quality clock sources.
239 */
240 saveintr = intr_disable();
241 x = *pps_ap[0]; /* state, must be first, see below */
242 y = *pps_ap[1]; /* timer2 */
243 z = *pps_ap[2]; /* timer1 */
244 intr_restore(saveintr);
245
246 /*
247 * Order is important here. We need to check the state of the GPIO
248 * pin first, in order to avoid reading timer 1 right before the
249 * state change. Technically pps_a may be zero in which case we
250 * harmlessly read the REVID register and the contents of pps_d is
251 * of no concern.
252 */
253
254 i = x & pps_d;
255
256 /* If state did not change or we don't have a GPIO pin, return */
257 if (i == state || pps_a == 0)
258 return;
259
260 state = i;
261
262 /* If the state is "low", flip the echo GPIO and return. */
263 if (!i) {
264 if (echo_a)
265 mmcrptr[(echo_a ^ 0xc) / 2] = echo_d;
266 return;
267 }
268
269 /*
270 * Subtract timer1 from timer2 to compensate for time from the
271 * edge until we read the counters.
272 */
273 u = y - z;
274
275 pps_capture(&elan_pps);
276 elan_pps.capcount = u;
277 pps_event(&elan_pps, PPS_CAPTUREASSERT);
278
279 /* Twiddle echo bit */
280 if (echo_a)
281 mmcrptr[echo_a / 2] = echo_d;
282 }
283 #endif /* CPU_ELAN_PPS */
284
285 static unsigned
286 elan_get_timecount(struct timecounter *tc)
287 {
288
289 /* Read timer2, end of story */
290 return (elan_mmcr->GPTMR2CNT);
291 }
292
293 /*
294 * The Elan CPU can be run from a number of clock frequencies, this
295 * allows you to override the default 33.3 MHZ.
296 */
297 #ifndef CPU_ELAN_XTAL
298 #define CPU_ELAN_XTAL 33333333
299 #endif
300
301 static struct timecounter elan_timecounter = {
302 elan_get_timecount,
303 NULL,
304 0xffff,
305 CPU_ELAN_XTAL / 4,
306 "ELAN",
307 1000
308 };
309
310 static int
311 sysctl_machdep_elan_freq(SYSCTL_HANDLER_ARGS)
312 {
313 u_int f;
314 int error;
315
316 f = elan_timecounter.tc_frequency * 4;
317 error = sysctl_handle_int(oidp, &f, 0, req);
318 if (error == 0 && req->newptr != NULL)
319 elan_timecounter.tc_frequency = (f + 3) / 4;
320 return (error);
321 }
322
323 SYSCTL_PROC(_machdep, OID_AUTO, elan_freq, CTLTYPE_UINT | CTLFLAG_RW,
324 0, sizeof (u_int), sysctl_machdep_elan_freq, "IU", "");
325
326 /*
327 * Positively identifying the Elan can only be done through the PCI id of
328 * the host-bridge, this function is called from i386/pci/pci_bus.c.
329 */
330 void
331 init_AMD_Elan_sc520(void)
332 {
333 u_int new;
334 int i;
335
336 mmcrptr = pmap_mapdev(0xfffef000, 0x1000);
337 elan_mmcr = (volatile struct elan_mmcr *)mmcrptr;
338
339 /*-
340 * The i8254 is driven with a nonstandard frequency which is
341 * derived thusly:
342 * f = 32768 * 45 * 25 / 31 = 1189161.29...
343 * We use the sysctl to get the i8254 (timecounter etc) into whack.
344 */
345
346 new = 1189161;
347 i = kernel_sysctlbyname(&thread0, "machdep.i8254_freq",
348 NULL, 0, &new, sizeof new, NULL, 0);
349 if (bootverbose || 1)
350 printf("sysctl machdep.i8254_freq=%d returns %d\n", new, i);
351
352 /* Start GP timer #2 and use it as timecounter, hz permitting */
353 elan_mmcr->GPTMR2MAXCMPA = 0;
354 elan_mmcr->GPTMR2CTL = 0xc001;
355
356 #ifdef CPU_ELAN_PPS
357 /* Set up GP timer #1 as pps counter */
358 elan_mmcr->CSPFS &= ~0x10;
359 elan_mmcr->GPTMR1CTL = 0x8000 | 0x4000 | 0x10 | 0x1;
360 elan_mmcr->GPTMR1MAXCMPA = 0x0;
361 elan_mmcr->GPTMR1MAXCMPB = 0x0;
362 elan_pps.ppscap |= PPS_CAPTUREASSERT;
363 pps_init(&elan_pps);
364 #endif
365 tc_init(&elan_timecounter);
366 }
367
368 static void
369 elan_watchdog(void *foo __unused, u_int spec, int *error)
370 {
371 u_int u, v, w;
372 static u_int cur;
373
374 u = spec & WD_INTERVAL;
375 if (u > 0 && u <= 35) {
376 u = imax(u - 5, 24);
377 v = 2 << (u - 24);
378 v |= 0xc000;
379
380 /*
381 * There is a bug in some silicon which prevents us from
382 * writing to the WDTMRCTL register if the GP echo mode is
383 * enabled. GP echo mode on the other hand is desirable
384 * for other reasons. Save and restore the GP echo mode
385 * around our hardware tom-foolery.
386 */
387 w = elan_mmcr->GPECHO;
388 elan_mmcr->GPECHO = 0;
389 if (v != cur) {
390 /* Clear the ENB bit */
391 elan_mmcr->WDTMRCTL = 0x3333;
392 elan_mmcr->WDTMRCTL = 0xcccc;
393 elan_mmcr->WDTMRCTL = 0;
394
395 /* Set new value */
396 elan_mmcr->WDTMRCTL = 0x3333;
397 elan_mmcr->WDTMRCTL = 0xcccc;
398 elan_mmcr->WDTMRCTL = v;
399 cur = v;
400 } else {
401 /* Just reset timer */
402 elan_mmcr->WDTMRCTL = 0xaaaa;
403 elan_mmcr->WDTMRCTL = 0x5555;
404 }
405 elan_mmcr->GPECHO = w;
406 *error = 0;
407 } else {
408 w = elan_mmcr->GPECHO;
409 elan_mmcr->GPECHO = 0;
410 elan_mmcr->WDTMRCTL = 0x3333;
411 elan_mmcr->WDTMRCTL = 0xcccc;
412 elan_mmcr->WDTMRCTL = 0x4080;
413 elan_mmcr->WDTMRCTL = w; /* XXX What does this statement do? */
414 elan_mmcr->GPECHO = w;
415 cur = 0;
416 }
417 }
418
419 static int
420 elan_mmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
421 int nprot, vm_memattr_t *memattr)
422 {
423
424 if (offset >= 0x1000)
425 return (-1);
426 *paddr = 0xfffef000;
427 return (0);
428 }
429 static int
430 elan_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *tdr)
431 {
432 int error;
433
434 error = ENOIOCTL;
435
436 #ifdef CPU_ELAN_PPS
437 if (pps_a != 0)
438 error = pps_ioctl(cmd, arg, &elan_pps);
439 /*
440 * We only want to incur the overhead of the PPS polling if we
441 * are actually asked to timestamp.
442 */
443 if (elan_pps.ppsparam.mode & PPS_CAPTUREASSERT) {
444 elan_timecounter.tc_poll_pps = elan_poll_pps;
445 } else {
446 elan_timecounter.tc_poll_pps = NULL;
447 }
448 if (error != ENOIOCTL)
449 return (error);
450 #endif
451
452 return(error);
453 }
454
455 static struct cdevsw elan_cdevsw = {
456 .d_version = D_VERSION,
457 .d_flags = D_NEEDGIANT,
458 .d_ioctl = elan_ioctl,
459 .d_mmap = elan_mmap,
460 .d_name = "elan",
461 };
462
463 static void
464 elan_drvinit(void)
465 {
466
467 #ifdef CPU_SOEKRIS
468 #define BIOS_OEM_MAXLEN 72
469 static u_char bios_oem[BIOS_OEM_MAXLEN] = "\0";
470 #endif /* CPU_SOEKRIS */
471
472 /* If no elan found, just return */
473 if (mmcrptr == NULL)
474 return;
475
476 printf("Elan-mmcr driver: MMCR at %p.%s\n",
477 mmcrptr,
478 #ifdef CPU_ELAN_PPS
479 " PPS support."
480 #else
481 ""
482 #endif
483 );
484
485 make_dev(&elan_cdevsw, 0,
486 UID_ROOT, GID_WHEEL, 0600, "elan-mmcr");
487
488 #ifdef CPU_SOEKRIS
489 if ( bios_oem_strings(&bios_soekris, bios_oem, BIOS_OEM_MAXLEN) > 0 )
490 printf("Elan-mmcr %s\n", bios_oem);
491
492 /* Create the error LED on GPIO9 */
493 led_cookie[9] = 0x02000c34;
494 led_dev[9] = led_create(gpio_led, &led_cookie[9], "error");
495
496 /* Disable the unavailable GPIO pins */
497 strcpy(gpio_config, "-----....--..--------..---------");
498 #else /* !CPU_SOEKRIS */
499 /* We don't know which pins are available so enable them all */
500 strcpy(gpio_config, "................................");
501 #endif /* CPU_SOEKRIS */
502
503 EVENTHANDLER_REGISTER(watchdog_list, elan_watchdog, NULL, 0);
504 }
505
506 SYSINIT(elan, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, elan_drvinit, NULL);
507
Cache object: 9706fb82f1f4add39826c0743c153f26
|