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