elan-mmcr.c revision 123015
1119452Sobrien/*-
2101225Sphk * ----------------------------------------------------------------------------
3101225Sphk * "THE BEER-WARE LICENSE" (Revision 42):
4101225Sphk * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
5101225Sphk * can do whatever you want with this stuff. If we meet some day, and you think
6101225Sphk * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7101225Sphk * ----------------------------------------------------------------------------
8101225Sphk *
9101225Sphk *
10102934Sphk * The AMD Elan sc520 is a system-on-chip gadget which is used in embedded
11102934Sphk * kind of things, see www.soekris.com for instance, and it has a few quirks
12102934Sphk * we need to deal with.
13102934Sphk * Unfortunately we cannot identify the gadget by CPUID output because it
14102934Sphk * depends on strapping options and only the stepping field may be useful
15102934Sphk * and those are undocumented from AMDs side.
16102934Sphk *
17102934Sphk * So instead we recognize the on-chip host-PCI bridge and call back from
18102934Sphk * sys/i386/pci/pci_bus.c to here if we find it.
19109327Sphk *
20123015Sphk * #ifdef CPU_ELAN_PPS
21123015Sphk *   The Elan has three general purpose counters, and when two of these
22123015Sphk *   are used just right they can hardware timestamp external events with
23123015Sphk *   approx 125 nsec resolution and +/- 125 nsec precision.
24123015Sphk *
25123015Sphk *   Connect the signal to TMR1IN and a GPIO pin, and configure the GPIO pin
26123015Sphk *   with a 'P' in sysctl machdep.elan_gpio_config.
27123015Sphk *
28123015Sphk *   The rising edge of the signal will start timer 1 counting up from
29123015Sphk *   zero, and when the timecounter polls for PPS, both counter 1 & 2 is
30123015Sphk *   read, as well as the GPIO bit.  If a rising edge has happened, the
31123015Sphk *   contents of timer 1 which is how long time ago the edge happened,
32123015Sphk *   is subtracted from timer 2 to give us a "true time stamp".
33123015Sphk *
34123015Sphk *   Echoing the PPS signal on any GPIO pin is supported (set it to 'e'
35123015Sphk *   or 'E' (inverted) in the sysctl)  The echo signal should only be
36123015Sphk *   used as a visual indication, not for calibration since it suffers
37123015Sphk *   from 1/hz (or more) jitter which the timestamps are compensated for.
38123015Sphk * #endif CPU_ELAN_PPS
39101225Sphk */
40102934Sphk
41115683Sobrien#include <sys/cdefs.h>
42115683Sobrien__FBSDID("$FreeBSD: head/sys/i386/i386/elan-mmcr.c 123015 2003-11-27 20:27:29Z phk $");
43115683Sobrien
44111138Sphk#include "opt_cpu.h"
45101225Sphk#include <sys/param.h>
46101225Sphk#include <sys/systm.h>
47101225Sphk#include <sys/kernel.h>
48101225Sphk#include <sys/conf.h>
49102934Sphk#include <sys/sysctl.h>
50123015Sphk#include <sys/syslog.h>
51102934Sphk#include <sys/timetc.h>
52102934Sphk#include <sys/proc.h>
53103482Sphk#include <sys/uio.h>
54103482Sphk#include <sys/lock.h>
55103482Sphk#include <sys/mutex.h>
56103482Sphk#include <sys/malloc.h>
57109327Sphk#include <sys/sysctl.h>
58109327Sphk#include <sys/timepps.h>
59111647Sphk#include <sys/watchdog.h>
60101225Sphk
61121944Sphk#include <dev/led/led.h>
62101225Sphk#include <machine/md_var.h>
63101225Sphk
64102934Sphk#include <vm/vm.h>
65102934Sphk#include <vm/pmap.h>
66102934Sphk
67123015Sphkstatic char gpio_config[33];
68123015Sphk
69102934Sphkuint16_t *elan_mmcr;
70102934Sphk
71123015Sphk#ifdef CPU_ELAN_PPS
72109327Sphkstatic struct pps_state elan_pps;
73123015Sphku_int	pps_a, pps_d;
74123015Sphku_int	echo_a, echo_d;
75123015Sphk#endif /* CPU_ELAN_PPS */
76123015Sphku_int	led_cookie[32];
77123015Sphkdev_t	led_dev[32];
78109327Sphk
79109327Sphkstatic void
80123015Sphkgpio_led(void *cookie, int state)
81123015Sphk{
82123015Sphk	u_int u, v;
83123015Sphk
84123015Sphk	u = *(int *)cookie;
85123015Sphk	v = u & 0xffff;
86123015Sphk	u >>= 16;
87123015Sphk	if (!state)
88123015Sphk		v ^= 0xc;
89123015Sphk	elan_mmcr[v / 2] = u;
90123015Sphk}
91123015Sphk
92123015Sphkstatic int
93123015Sphksysctl_machdep_elan_gpio_config(SYSCTL_HANDLER_ARGS)
94123015Sphk{
95123015Sphk	u_int u, v;
96123015Sphk	int i, np, ne;
97123015Sphk	int error;
98123015Sphk	char buf[32], tmp[10];
99123015Sphk
100123015Sphk	error = SYSCTL_OUT(req, gpio_config, 33);
101123015Sphk	if (error != 0 || req->newptr == NULL)
102123015Sphk		return (error);
103123015Sphk	if (req->newlen != 32)
104123015Sphk		return (EINVAL);
105123015Sphk	error = SYSCTL_IN(req, buf, 32);
106123015Sphk	if (error != 0)
107123015Sphk		return (error);
108123015Sphk	/* Disallow any disabled pins and count pps and echo */
109123015Sphk	np = ne = 0;
110123015Sphk	for (i = 0; i < 32; i++) {
111123015Sphk		if (gpio_config[i] == '-' && (buf[i] != '-' && buf[i] != '.'))
112123015Sphk			return (EPERM);
113123015Sphk		if (buf[i] == 'P') {
114123015Sphk			np++;
115123015Sphk			if (np > 1)
116123015Sphk				return (EINVAL);
117123015Sphk		}
118123015Sphk		if (buf[i] == 'e' || buf[i] == 'E') {
119123015Sphk			ne++;
120123015Sphk			if (ne > 1)
121123015Sphk				return (EINVAL);
122123015Sphk		}
123123015Sphk		if (buf[i] != 'L' && buf[i] != 'l'
124123015Sphk#ifdef CPU_ELAN_PPS
125123015Sphk		    && buf[i] != 'P' && buf[i] != 'E' && buf[i] != 'e'
126123015Sphk#endif /* CPU_ELAN_PPS */
127123015Sphk		    && buf[i] != '.' && buf[i] != '-')
128123015Sphk			return (EINVAL);
129123015Sphk	}
130123015Sphk#ifdef CPU_ELAN_PPS
131123015Sphk	if (np == 0)
132123015Sphk		pps_a = pps_d = 0;
133123015Sphk	if (ne == 0)
134123015Sphk		echo_a = echo_d = 0;
135123015Sphk#endif
136123015Sphk	for (i = 0; i < 32; i++) {
137123015Sphk		u = 1 << (i & 0xf);
138123015Sphk		if (i >= 16)
139123015Sphk			v = 2;
140123015Sphk		else
141123015Sphk			v = 0;
142123015Sphk		if (buf[i] != 'l' && buf[i] != 'L' && led_dev[i] != NULL) {
143123015Sphk			led_destroy(led_dev[i]);
144123015Sphk			led_dev[i] = NULL;
145123015Sphk			elan_mmcr[(0xc2a + v) / 2] &= ~u;
146123015Sphk		}
147123015Sphk		switch (buf[i]) {
148123015Sphk#ifdef CPU_ELAN_PPS
149123015Sphk		case 'P':
150123015Sphk			pps_d = u;
151123015Sphk			pps_a = 0xc30 + v;
152123015Sphk			elan_mmcr[(0xc2a + v) / 2] &= ~u;
153123015Sphk			gpio_config[i] = buf[i];
154123015Sphk			break;
155123015Sphk		case 'e':
156123015Sphk		case 'E':
157123015Sphk			echo_d = u;
158123015Sphk			if (buf[i] == 'E')
159123015Sphk				echo_a = 0xc34 + v;
160123015Sphk			else
161123015Sphk				echo_a = 0xc38 + v;
162123015Sphk			elan_mmcr[(0xc2a + v) / 2] |= u;
163123015Sphk			gpio_config[i] = buf[i];
164123015Sphk			break;
165123015Sphk#endif /* CPU_ELAN_PPS */
166123015Sphk		case 'l':
167123015Sphk		case 'L':
168123015Sphk			if (buf[i] == 'L')
169123015Sphk				led_cookie[i] = (0xc34 + v) | (u << 16);
170123015Sphk			else
171123015Sphk				led_cookie[i] = (0xc38 + v) | (u << 16);
172123015Sphk			if (led_dev[i])
173123015Sphk				break;
174123015Sphk			sprintf(tmp, "gpio%d", i);
175123015Sphk			led_dev[i] =
176123015Sphk			    led_create(gpio_led, &led_cookie[i], tmp);
177123015Sphk			elan_mmcr[(0xc2a + v) / 2] |= u;
178123015Sphk			gpio_config[i] = buf[i];
179123015Sphk			break;
180123015Sphk		case '.':
181123015Sphk			gpio_config[i] = buf[i];
182123015Sphk			break;
183123015Sphk		case '-':
184123015Sphk		default:
185123015Sphk			break;
186123015Sphk		}
187123015Sphk	}
188123015Sphk	return (0);
189123015Sphk}
190123015Sphk
191123015SphkSYSCTL_OID(_machdep, OID_AUTO, elan_gpio_config, CTLTYPE_STRING | CTLFLAG_RW,
192123015Sphk    NULL, 0, sysctl_machdep_elan_gpio_config, "A", "Elan CPU GPIO pin config");
193123015Sphk
194123015Sphk#ifdef CPU_ELAN_PPS
195123015Sphkstatic void
196109327Sphkelan_poll_pps(struct timecounter *tc)
197109327Sphk{
198109327Sphk	static int state;
199109327Sphk	int i;
200123015Sphk	u_int u;
201109327Sphk
202123015Sphk	/*
203123015Sphk	 * Order is important here.  We need to check the state of the GPIO
204123015Sphk	 * pin first, in order to avoid reading timer 1 right before the
205123015Sphk	 * state change.  Technically pps_a may be zero in which case we
206123015Sphk	 * harmlessly read the REVID register and the contents of pps_d is
207123015Sphk	 * of no concern.
208123015Sphk	 */
209123015Sphk	i = elan_mmcr[pps_a / 2] & pps_d;
210123015Sphk
211123015Sphk	/*
212123015Sphk	 * Subtract timer1 from timer2 to compensate for time from the
213123015Sphk	 * edge until now.
214123015Sphk	 */
215123015Sphk	u = elan_mmcr[0xc84 / 2] - elan_mmcr[0xc7c / 2];
216123015Sphk
217123015Sphk	/* If state did not change or we don't have a GPIO pin, return */
218123015Sphk	if (i == state || pps_a == 0)
219109327Sphk		return;
220123015Sphk
221109327Sphk	state = i;
222123015Sphk
223123015Sphk	/* If the state is "low", flip the echo GPIO and return.  */
224123015Sphk	if (!i) {
225123015Sphk		if (echo_a)
226123015Sphk			elan_mmcr[(echo_a ^ 0xc) / 2] = echo_d;
227109327Sphk		return;
228123015Sphk	}
229123015Sphk
230123015Sphk	/* State is "high", record the pps data */
231109327Sphk	pps_capture(&elan_pps);
232123015Sphk	elan_pps.capcount = u & 0xffff;
233109327Sphk	pps_event(&elan_pps, PPS_CAPTUREASSERT);
234123015Sphk
235123015Sphk	/* Twiddle echo bit */
236123015Sphk	if (echo_a)
237123015Sphk		elan_mmcr[echo_a / 2] = echo_d;
238109327Sphk}
239123015Sphk#endif /* CPU_ELAN_PPS */
240109327Sphk
241102935Sphkstatic unsigned
242102935Sphkelan_get_timecount(struct timecounter *tc)
243102935Sphk{
244123015Sphk
245123015Sphk	/* Read timer2, end of story */
246102935Sphk	return (elan_mmcr[0xc84 / 2]);
247102935Sphk}
248102935Sphk
249109327Sphk/*
250109327Sphk * The Elan CPU can be run from a number of clock frequencies, this
251109327Sphk * allows you to override the default 33.3 MHZ.
252109327Sphk */
253123015Sphk#ifndef CPU_ELAN_XTAL
254123015Sphk#define CPU_ELAN_XTAL 33333333
255109327Sphk#endif
256109327Sphk
257102935Sphkstatic struct timecounter elan_timecounter = {
258102935Sphk	elan_get_timecount,
259109327Sphk	NULL,
260102935Sphk	0xffff,
261123015Sphk	CPU_ELAN_XTAL / 4,
262119715Sphk	"ELAN",
263119715Sphk	1000
264102935Sphk};
265102935Sphk
266109327Sphkstatic int
267109327Sphksysctl_machdep_elan_freq(SYSCTL_HANDLER_ARGS)
268109327Sphk{
269109327Sphk	u_int f;
270109327Sphk	int error;
271109327Sphk
272109327Sphk	f = elan_timecounter.tc_frequency * 4;
273109327Sphk	error = sysctl_handle_int(oidp, &f, sizeof(f), req);
274109327Sphk	if (error == 0 && req->newptr != NULL)
275109327Sphk		elan_timecounter.tc_frequency = (f + 3) / 4;
276109327Sphk	return (error);
277109327Sphk}
278109327Sphk
279109327SphkSYSCTL_PROC(_machdep, OID_AUTO, elan_freq, CTLTYPE_UINT | CTLFLAG_RW,
280109327Sphk    0, sizeof (u_int), sysctl_machdep_elan_freq, "IU", "");
281109327Sphk
282123015Sphk/*
283123015Sphk * Positively identifying the Elan can only be done through the PCI id of
284123015Sphk * the host-bridge, this function is called from i386/pci/pci_bus.c.
285123015Sphk */
286102934Sphkvoid
287102934Sphkinit_AMD_Elan_sc520(void)
288102934Sphk{
289102934Sphk	u_int new;
290102934Sphk	int i;
291102934Sphk
292102934Sphk	elan_mmcr = pmap_mapdev(0xfffef000, 0x1000);
293102934Sphk
294102934Sphk	/*-
295102934Sphk	 * The i8254 is driven with a nonstandard frequency which is
296102934Sphk	 * derived thusly:
297102934Sphk	 *   f = 32768 * 45 * 25 / 31 = 1189161.29...
298123015Sphk	 * We use the sysctl to get the i8254 (timecounter etc) into whack.
299102934Sphk	 */
300102934Sphk
301102934Sphk	new = 1189161;
302102934Sphk	i = kernel_sysctlbyname(&thread0, "machdep.i8254_freq",
303123015Sphk	    NULL, 0, &new, sizeof new, NULL);
304123015Sphk	if (bootverbose || 1)
305103168Ssam		printf("sysctl machdep.i8254_freq=%d returns %d\n", new, i);
306102935Sphk
307102935Sphk	/* Start GP timer #2 and use it as timecounter, hz permitting */
308123015Sphk	elan_mmcr[0xc8e / 2] = 0x0;
309102935Sphk	elan_mmcr[0xc82 / 2] = 0xc001;
310109327Sphk
311123015Sphk#ifdef CPU_ELAN_PPS
312109327Sphk	/* Set up GP timer #1 as pps counter */
313109327Sphk	elan_mmcr[0xc24 / 2] &= ~0x10;
314109327Sphk	elan_mmcr[0xc7a / 2] = 0x8000 | 0x4000 | 0x10 | 0x1;
315123015Sphk	elan_mmcr[0xc7e / 2] = 0x0;
316123015Sphk	elan_mmcr[0xc80 / 2] = 0x0;
317109327Sphk	elan_pps.ppscap |= PPS_CAPTUREASSERT;
318109327Sphk	pps_init(&elan_pps);
319109327Sphk#endif
320102935Sphk	tc_init(&elan_timecounter);
321102934Sphk}
322102934Sphk
323101225Sphkstatic d_ioctl_t elan_ioctl;
324101225Sphkstatic d_mmap_t elan_mmap;
325101225Sphk
326101225Sphkstatic struct cdevsw elan_cdevsw = {
327111815Sphk	.d_ioctl =	elan_ioctl,
328111815Sphk	.d_mmap =	elan_mmap,
329111815Sphk	.d_name =	"elan",
330101225Sphk};
331101225Sphk
332103482Sphkstatic void
333103482Sphkelan_drvinit(void)
334101225Sphk{
335103482Sphk
336123015Sphk	/* If no elan found, just return */
337103482Sphk	if (elan_mmcr == NULL)
338103482Sphk		return;
339123015Sphk
340123015Sphk	printf("Elan-mmcr driver: MMCR at %p.%s\n",
341123015Sphk	    elan_mmcr,
342123015Sphk#ifdef CPU_ELAN_PPS
343123015Sphk	    " PPS support."
344123015Sphk#else
345123015Sphk	    ""
346123015Sphk#endif
347123015Sphk	    );
348123015Sphk
349123015Sphk	make_dev(&elan_cdevsw, 0,
350103482Sphk	    UID_ROOT, GID_WHEEL, 0600, "elan-mmcr");
351121944Sphk
352121944Sphk#ifdef CPU_SOEKRIS
353123015Sphk	/* Create the error LED on GPIO9 */
354123015Sphk	led_cookie[9] = 0x02000c34;
355123015Sphk	led_dev[9] = led_create(gpio_led, &led_cookie[9], "error");
356123015Sphk
357123015Sphk	/* Disable the unavailable GPIO pins */
358123015Sphk	strcpy(gpio_config, "-----....--..--------..---------");
359123015Sphk#else /* !CPU_SOEKRIS */
360123015Sphk	/* We don't know which pins are available so enable them all */
361123015Sphk	strcpy(gpio_config, "................................");
362121944Sphk#endif /* CPU_SOEKRIS */
363101225Sphk}
364101225Sphk
365121942SphkSYSINIT(elan, SI_SUB_PSEUDO, SI_ORDER_MIDDLE, elan_drvinit, NULL);
366103482Sphk
367101225Sphkstatic int
368112569Sjakeelan_mmap(dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, int nprot)
369101225Sphk{
370103482Sphk
371101225Sphk	if (offset >= 0x1000)
372101225Sphk		return (-1);
373111462Smux	*paddr = 0xfffef000;
374111462Smux	return (0);
375101225Sphk}
376101225Sphk
377101225Sphkstatic int
378111647Sphkelan_watchdog(u_int spec)
379111647Sphk{
380111647Sphk	u_int u, v;
381111647Sphk	static u_int cur;
382111647Sphk
383111647Sphk	if (spec & ~__WD_LEGAL)
384111647Sphk		return (EINVAL);
385111647Sphk	switch (spec & (WD_ACTIVE|WD_PASSIVE)) {
386111647Sphk	case WD_ACTIVE:
387111647Sphk		u = spec & WD_INTERVAL;
388111647Sphk		if (u > 35)
389111647Sphk			return (EINVAL);
390111647Sphk		u = imax(u - 5, 24);
391111647Sphk		v = 2 << (u - 24);
392111647Sphk		v |= 0xc000;
393111647Sphk
394111647Sphk		/*
395111647Sphk		 * There is a bug in some silicon which prevents us from
396111647Sphk		 * writing to the WDTMRCTL register if the GP echo mode is
397111647Sphk		 * enabled.  GP echo mode on the other hand is desirable
398111647Sphk		 * for other reasons.  Save and restore the GP echo mode
399111647Sphk		 * around our hardware tom-foolery.
400111647Sphk		 */
401111647Sphk		u = elan_mmcr[0xc00 / 2];
402111647Sphk		elan_mmcr[0xc00 / 2] = 0;
403111647Sphk		if (v != cur) {
404111647Sphk			/* Clear the ENB bit */
405111647Sphk			elan_mmcr[0xcb0 / 2] = 0x3333;
406111647Sphk			elan_mmcr[0xcb0 / 2] = 0xcccc;
407111647Sphk			elan_mmcr[0xcb0 / 2] = 0;
408111647Sphk
409111647Sphk			/* Set new value */
410111647Sphk			elan_mmcr[0xcb0 / 2] = 0x3333;
411111647Sphk			elan_mmcr[0xcb0 / 2] = 0xcccc;
412111647Sphk			elan_mmcr[0xcb0 / 2] = v;
413111647Sphk			cur = v;
414111647Sphk		} else {
415111647Sphk			/* Just reset timer */
416111647Sphk			elan_mmcr[0xcb0 / 2] = 0xaaaa;
417111647Sphk			elan_mmcr[0xcb0 / 2] = 0x5555;
418111647Sphk		}
419111647Sphk		elan_mmcr[0xc00 / 2] = u;
420111647Sphk		return (0);
421111647Sphk	case WD_PASSIVE:
422111647Sphk		return (EOPNOTSUPP);
423111647Sphk	case 0:
424111647Sphk		u = elan_mmcr[0xc00 / 2];
425111647Sphk		elan_mmcr[0xc00 / 2] = 0;
426111647Sphk		elan_mmcr[0xcb0 / 2] = 0x3333;
427111647Sphk		elan_mmcr[0xcb0 / 2] = 0xcccc;
428111647Sphk		elan_mmcr[0xcb0 / 2] = 0x4080;
429111647Sphk		elan_mmcr[0xc00 / 2] = u;
430111647Sphk		cur = 0;
431111647Sphk		return (0);
432111647Sphk	default:
433111647Sphk		return (EINVAL);
434111647Sphk	}
435111647Sphk
436111647Sphk}
437111647Sphk
438111647Sphkstatic int
439101225Sphkelan_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct  thread *tdr)
440101225Sphk{
441109327Sphk	int error;
442109327Sphk
443109327Sphk	error = ENOTTY;
444123015Sphk
445123015Sphk#ifdef CPU_ELAN_PPS
446123015Sphk	if (pps_a != 0)
447123015Sphk		error = pps_ioctl(cmd, arg, &elan_pps);
448109327Sphk	/*
449109327Sphk	 * We only want to incur the overhead of the PPS polling if we
450109327Sphk	 * are actually asked to timestamp.
451109327Sphk	 */
452123015Sphk	if (elan_pps.ppsparam.mode & PPS_CAPTUREASSERT) {
453109327Sphk		elan_timecounter.tc_poll_pps = elan_poll_pps;
454123015Sphk	} else {
455109327Sphk		elan_timecounter.tc_poll_pps = NULL;
456123015Sphk	}
457109327Sphk	if (error != ENOTTY)
458109327Sphk		return (error);
459123015Sphk#endif
460109327Sphk
461111647Sphk	if (cmd == WDIOCPATPAT)
462111647Sphk		return elan_watchdog(*((u_int*)arg));
463111647Sphk
464109327Sphk	/* Other future ioctl handling here */
465109327Sphk	return(error);
466101225Sphk}
467101225Sphk
468