summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPoul-Henning Kamp <phk@FreeBSD.org>2004-01-05 12:00:59 +0000
committerPoul-Henning Kamp <phk@FreeBSD.org>2004-01-05 12:00:59 +0000
commit883bd55abd9f5910c6706cb8245bfdaf1d6ac356 (patch)
treef18fcd1e48c29638fcdd4114e9a671971a5b6d39
parentc2f1dd4d714cabc12822319e75bd5d6ac28e87b6 (diff)
Notes
-rw-r--r--sys/i386/i386/elan-mmcr.c78
-rw-r--r--sys/i386/i386/vm_machdep.c10
-rw-r--r--sys/i386/include/elan_mmcr.h280
-rw-r--r--sys/i386/include/md_var.h1
4 files changed, 331 insertions, 38 deletions
diff --git a/sys/i386/i386/elan-mmcr.c b/sys/i386/i386/elan-mmcr.c
index 876193c52a01..9e3de8f5ef41 100644
--- a/sys/i386/i386/elan-mmcr.c
+++ b/sys/i386/i386/elan-mmcr.c
@@ -60,13 +60,15 @@ __FBSDID("$FreeBSD$");
#include <dev/led/led.h>
#include <machine/md_var.h>
+#include <machine/elan_mmcr.h>
#include <vm/vm.h>
#include <vm/pmap.h>
static char gpio_config[33];
-uint16_t *elan_mmcr;
+static volatile uint16_t *mmcrptr;
+volatile struct elan_mmcr * elan_mmcr;
#ifdef CPU_ELAN_PPS
static struct pps_state elan_pps;
@@ -86,7 +88,7 @@ gpio_led(void *cookie, int state)
u >>= 16;
if (!state)
v ^= 0xc;
- elan_mmcr[v / 2] = u;
+ mmcrptr[v / 2] = u;
}
static int
@@ -142,14 +144,14 @@ sysctl_machdep_elan_gpio_config(SYSCTL_HANDLER_ARGS)
if (buf[i] != 'l' && buf[i] != 'L' && led_dev[i] != NULL) {
led_destroy(led_dev[i]);
led_dev[i] = NULL;
- elan_mmcr[(0xc2a + v) / 2] &= ~u;
+ mmcrptr[(0xc2a + v) / 2] &= ~u;
}
switch (buf[i]) {
#ifdef CPU_ELAN_PPS
case 'P':
pps_d = u;
pps_a = 0xc30 + v;
- elan_mmcr[(0xc2a + v) / 2] &= ~u;
+ mmcrptr[(0xc2a + v) / 2] &= ~u;
gpio_config[i] = buf[i];
break;
case 'e':
@@ -159,7 +161,7 @@ sysctl_machdep_elan_gpio_config(SYSCTL_HANDLER_ARGS)
echo_a = 0xc34 + v;
else
echo_a = 0xc38 + v;
- elan_mmcr[(0xc2a + v) / 2] |= u;
+ mmcrptr[(0xc2a + v) / 2] |= u;
gpio_config[i] = buf[i];
break;
#endif /* CPU_ELAN_PPS */
@@ -174,7 +176,7 @@ sysctl_machdep_elan_gpio_config(SYSCTL_HANDLER_ARGS)
sprintf(tmp, "gpio%d", i);
led_dev[i] =
led_create(gpio_led, &led_cookie[i], tmp);
- elan_mmcr[(0xc2a + v) / 2] |= u;
+ mmcrptr[(0xc2a + v) / 2] |= u;
gpio_config[i] = buf[i];
break;
case '.':
@@ -206,13 +208,13 @@ elan_poll_pps(struct timecounter *tc)
* harmlessly read the REVID register and the contents of pps_d is
* of no concern.
*/
- i = elan_mmcr[pps_a / 2] & pps_d;
+ i = mmcrptr[pps_a / 2] & pps_d;
/*
* Subtract timer1 from timer2 to compensate for time from the
* edge until now.
*/
- u = elan_mmcr[0xc84 / 2] - elan_mmcr[0xc7c / 2];
+ u = elan_mmcr->GPTMR2CNT - elan_mmcr->GPTMR1CNT;
/* If state did not change or we don't have a GPIO pin, return */
if (i == state || pps_a == 0)
@@ -223,7 +225,7 @@ elan_poll_pps(struct timecounter *tc)
/* If the state is "low", flip the echo GPIO and return. */
if (!i) {
if (echo_a)
- elan_mmcr[(echo_a ^ 0xc) / 2] = echo_d;
+ mmcrptr[(echo_a ^ 0xc) / 2] = echo_d;
return;
}
@@ -234,7 +236,7 @@ elan_poll_pps(struct timecounter *tc)
/* Twiddle echo bit */
if (echo_a)
- elan_mmcr[echo_a / 2] = echo_d;
+ mmcrptr[echo_a / 2] = echo_d;
}
#endif /* CPU_ELAN_PPS */
@@ -243,7 +245,7 @@ elan_get_timecount(struct timecounter *tc)
{
/* Read timer2, end of story */
- return (elan_mmcr[0xc84 / 2]);
+ return (elan_mmcr->GPTMR2CNT);
}
/*
@@ -289,7 +291,8 @@ init_AMD_Elan_sc520(void)
u_int new;
int i;
- elan_mmcr = pmap_mapdev(0xfffef000, 0x1000);
+ mmcrptr = pmap_mapdev(0xfffef000, 0x1000);
+ elan_mmcr = (volatile struct elan_mmcr *)mmcrptr;
/*-
* The i8254 is driven with a nonstandard frequency which is
@@ -305,15 +308,15 @@ init_AMD_Elan_sc520(void)
printf("sysctl machdep.i8254_freq=%d returns %d\n", new, i);
/* Start GP timer #2 and use it as timecounter, hz permitting */
- elan_mmcr[0xc8e / 2] = 0x0;
- elan_mmcr[0xc82 / 2] = 0xc001;
+ elan_mmcr->GPTMR2MAXCMPA = 0;
+ elan_mmcr->GPTMR2CTL = 0xc001;
#ifdef CPU_ELAN_PPS
/* Set up GP timer #1 as pps counter */
- elan_mmcr[0xc24 / 2] &= ~0x10;
- elan_mmcr[0xc7a / 2] = 0x8000 | 0x4000 | 0x10 | 0x1;
- elan_mmcr[0xc7e / 2] = 0x0;
- elan_mmcr[0xc80 / 2] = 0x0;
+ elan_mmcr->CSPFS &= ~0x10;
+ elan_mmcr->GPTMR1CTL = 0x8000 | 0x4000 | 0x10 | 0x1;
+ elan_mmcr->GPTMR1MAXCMPA = 0x0;
+ elan_mmcr->GPTMR1MAXCMPB = 0x0;
elan_pps.ppscap |= PPS_CAPTUREASSERT;
pps_init(&elan_pps);
#endif
@@ -334,11 +337,11 @@ elan_drvinit(void)
{
/* If no elan found, just return */
- if (elan_mmcr == NULL)
+ if (mmcrptr == NULL)
return;
printf("Elan-mmcr driver: MMCR at %p.%s\n",
- elan_mmcr,
+ mmcrptr,
#ifdef CPU_ELAN_PPS
" PPS support."
#else
@@ -398,35 +401,36 @@ elan_watchdog(u_int spec)
* for other reasons. Save and restore the GP echo mode
* around our hardware tom-foolery.
*/
- u = elan_mmcr[0xc00 / 2];
- elan_mmcr[0xc00 / 2] = 0;
+ u = elan_mmcr->GPECHO;
+ elan_mmcr->GPECHO = 0;
if (v != cur) {
/* Clear the ENB bit */
- elan_mmcr[0xcb0 / 2] = 0x3333;
- elan_mmcr[0xcb0 / 2] = 0xcccc;
- elan_mmcr[0xcb0 / 2] = 0;
+ elan_mmcr->WDTMRCTL = 0x3333;
+ elan_mmcr->WDTMRCTL = 0xcccc;
+ elan_mmcr->WDTMRCTL = 0;
/* Set new value */
- elan_mmcr[0xcb0 / 2] = 0x3333;
- elan_mmcr[0xcb0 / 2] = 0xcccc;
- elan_mmcr[0xcb0 / 2] = v;
+ elan_mmcr->WDTMRCTL = 0x3333;
+ elan_mmcr->WDTMRCTL = 0xcccc;
+ elan_mmcr->WDTMRCTL = v;
cur = v;
} else {
/* Just reset timer */
- elan_mmcr[0xcb0 / 2] = 0xaaaa;
- elan_mmcr[0xcb0 / 2] = 0x5555;
+ elan_mmcr->WDTMRCTL = 0xaaaa;
+ elan_mmcr->WDTMRCTL = 0x5555;
}
- elan_mmcr[0xc00 / 2] = u;
+ elan_mmcr->GPECHO = u;
return (0);
case WD_PASSIVE:
return (EOPNOTSUPP);
case 0:
- u = elan_mmcr[0xc00 / 2];
- elan_mmcr[0xc00 / 2] = 0;
- elan_mmcr[0xcb0 / 2] = 0x3333;
- elan_mmcr[0xcb0 / 2] = 0xcccc;
- elan_mmcr[0xcb0 / 2] = 0x4080;
- elan_mmcr[0xc00 / 2] = u;
+ u = elan_mmcr->GPECHO;
+ elan_mmcr->GPECHO = 0;
+ elan_mmcr->WDTMRCTL = 0x3333;
+ elan_mmcr->WDTMRCTL = 0xcccc;
+ elan_mmcr->WDTMRCTL = 0x4080;
+ elan_mmcr->WDTMRCTL = u;
+ elan_mmcr->GPECHO = u;
cur = 0;
return (0);
default:
diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c
index 238af52a9d0f..b09128d483c6 100644
--- a/sys/i386/i386/vm_machdep.c
+++ b/sys/i386/i386/vm_machdep.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include "opt_pc98.h"
#endif
#include "opt_reset.h"
+#include "opt_cpu.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -77,6 +78,10 @@ __FBSDID("$FreeBSD$");
#include <machine/pcb_ext.h>
#include <machine/vm86.h>
+#ifdef CPU_ELAN
+#include <machine/elan_mmcr.h>
+#endif
+
#include <vm/vm.h>
#include <vm/vm_extern.h>
#include <vm/vm_kern.h>
@@ -538,6 +543,11 @@ static void
cpu_reset_real()
{
+#ifdef CPU_ELAN
+ if (elan_mmcr != NULL)
+ elan_mmcr->RESCFG = 1;
+#endif
+
#ifdef PC98
/*
* Attempt to do a CPU reset via CPU reset port.
diff --git a/sys/i386/include/elan_mmcr.h b/sys/i386/include/elan_mmcr.h
new file mode 100644
index 000000000000..27f00bab9c2b
--- /dev/null
+++ b/sys/i386/include/elan_mmcr.h
@@ -0,0 +1,280 @@
+/*-
+ * Copyright (c) 2004 John Birrell
+ * All rights reserved.
+ *
+ * Please see src/share/examples/etc/bsd-style-copyright.
+ *
+ * AMD Elan SC520 Memory Mapped Configuration Region (MMCR).
+ *
+ * The layout of this structure is documented by AMD in the Elan SC520
+ * Microcontroller Register Set Manual. The field names match those
+ * described in that document. The overall structure size must be 4096
+ * bytes. Ignore fields with the 'pad' prefix - they are only present for
+ * alignment purposes.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MACHINE_ELAN_MMCR_H_
+#define _MACHINE_ELAN_MMCR_H_ 1
+
+struct elan_mmcr {
+ /* CPU */
+ u_int16_t REVID;
+ u_int8_t CPUCTL;
+ u_int8_t pad_0x003[0xd];
+
+ /* SDRAM Controller */
+ u_int16_t DRCCTL;
+ u_int16_t DRCTMCTL;
+ u_int16_t DRCCFG;
+ u_int16_t DRCBENDADR;
+ u_int8_t pad_0x01a[0x6];
+ u_int8_t ECCCTL;
+ u_int8_t ECCSTA;
+ u_int8_t ECCCKBPOS;
+ u_int8_t ECCCKTEST;
+ u_int32_t ECCSBADD;
+ u_int32_t ECCMBADD;
+ u_int8_t pad_0x02c[0x14];
+
+ /* SDRAM Buffer */
+ u_int8_t DBCTL;
+ u_int8_t pad_0x041[0xf];
+
+ /* ROM/Flash Controller */
+ u_int16_t BOOTCSCTL;
+ u_int8_t pad_0x052[0x2];
+ u_int16_t ROMCS1CTL;
+ u_int16_t ROMCS2CTL;
+ u_int8_t pad_0x058[0x8];
+
+ /* PCI Bus Host Bridge */
+ u_int16_t HBCTL;
+ u_int16_t HBTGTIRQCTL;
+ u_int16_t HBTGTIRQSTA;
+ u_int16_t HBMSTIRQCTL;
+ u_int16_t HBMSTIRQSTA;
+ u_int8_t pad_0x06a[0x2];
+ u_int32_t MSTINTADD;
+
+ /* System Arbitration */
+ u_int8_t SYSARBCTL;
+ u_int8_t PCIARBSTA;
+ u_int16_t SYSARBMENB;
+ u_int32_t ARBPRICTL;
+ u_int8_t pad_0x078[0x8];
+
+ /* System Address Mapping */
+ u_int32_t ADDDECCTL;
+ u_int32_t WPVSTA;
+ u_int32_t PAR0;
+ u_int32_t PAR1;
+ u_int32_t PAR2;
+ u_int32_t PAR3;
+ u_int32_t PAR4;
+ u_int32_t PAR5;
+ u_int32_t PAR6;
+ u_int32_t PAR7;
+ u_int32_t PAR8;
+ u_int32_t PAR9;
+ u_int32_t PAR10;
+ u_int32_t PAR11;
+ u_int32_t PAR12;
+ u_int32_t PAR13;
+ u_int32_t PAR14;
+ u_int32_t PAR15;
+ u_int8_t pad_0x0c8[0xb38];
+
+ /* GP Bus Controller */
+ u_int8_t GPECHO;
+ u_int8_t GPCSDW;
+ u_int16_t GPCSQUAL;
+ u_int8_t pad_0xc04[0x4];
+ u_int8_t GPCSRT;
+ u_int8_t GPCSPW;
+ u_int8_t GPCSOFF;
+ u_int8_t GPRDW;
+ u_int8_t GPRDOFF;
+ u_int8_t GPWRW;
+ u_int8_t GPWROFF;
+ u_int8_t GPALEW;
+ u_int8_t GPALEOFF;
+ u_int8_t pad_0xc11[0xf];
+
+ /* Programmable Input/Output */
+ u_int16_t PIOPFS15_0;
+ u_int16_t PIOPFS31_16;
+ u_int8_t CSPFS;
+ u_int8_t pad_0xc25;
+ u_int8_t CLKSEL;
+ u_int8_t pad_0xc27;
+ u_int16_t DSCTL;
+ u_int16_t PIODIR15_0;
+ u_int16_t PIODIR31_16;
+ u_int8_t pad_0xc2e[0x2];
+ u_int16_t PIODATA15_0;
+ u_int16_t PIODATA31_16;
+ u_int16_t PIOSET15_0;
+ u_int16_t PIOSET31_16;
+ u_int16_t PIOCLR15_0;
+ u_int16_t PIOCLR31_16;
+ u_int8_t pad_0xc3c[0x24];
+
+ /* Software Timer */
+ u_int16_t SWTMRMILLI;
+ u_int16_t SWTMRMICRO;
+ u_int8_t SWTMRCFG;
+ u_int8_t pad_0xc65[0xb];
+
+ /* General-Purpose Timers */
+ u_int8_t GPTMRSTA;
+ u_int8_t pad_0xc71;
+ u_int16_t GPTMR0CTL;
+ u_int16_t GPTMR0CNT;
+ u_int16_t GPTMR0MAXCMPA;
+ u_int16_t GPTMR0MAXCMPB;
+ u_int16_t GPTMR1CTL;
+ u_int16_t GPTMR1CNT;
+ u_int16_t GPTMR1MAXCMPA;
+ u_int16_t GPTMR1MAXCMPB;
+ u_int16_t GPTMR2CTL;
+ u_int16_t GPTMR2CNT;
+ u_int8_t pad_0xc86[0x8];
+ u_int16_t GPTMR2MAXCMPA;
+ u_int8_t pad_0xc90[0x20];
+
+ /* Watchdog Timer */
+ u_int16_t WDTMRCTL;
+ u_int16_t WDTMRCNTL;
+ u_int16_t WDTMRCNTH;
+ u_int8_t pad_0xcb6[0xa];
+
+ /* UART Serial Ports */
+ u_int8_t UART1CTL;
+ u_int8_t UART1STA;
+ u_int8_t UART1FCRSHAD;
+ u_int8_t pad_0xcc3;
+ u_int8_t UART2CTL;
+ u_int8_t UART2STA;
+ u_int8_t UART2FCRSHAD;
+ u_int8_t pad_0xcc7[0x9];
+
+ /* Synchronous Serial Interface */
+ u_int8_t SSICTL;
+ u_int8_t SSIXMIT;
+ u_int8_t SSICMD;
+ u_int8_t SSISTA;
+ u_int8_t SSIRCV;
+ u_int8_t pad_0xcd5[0x2b];
+
+ /* Programmable Interrupt Controller */
+ u_int8_t PICICR;
+ u_int8_t pad_0xd01;
+ u_int8_t MPICMODE;
+ u_int8_t SL1PICMODE;
+ u_int8_t SL2PICMODE;
+ u_int8_t pad_0xd05[0x3];
+ u_int16_t SWINT16_1;
+ u_int8_t SWINT22_17;
+ u_int8_t pad_0xd0b[0x5];
+ u_int16_t INTPINPOL;
+ u_int8_t pad_0xd12[0x2];
+ u_int16_t PCIHOSTMAP;
+ u_int8_t pad_0xd16[0x2];
+ u_int16_t ECCMAP;
+ u_int8_t GPTMR0MAP;
+ u_int8_t GPTMR1MAP;
+ u_int8_t GPTMR2MAP;
+ u_int8_t pad_0xd1d[0x3];
+ u_int8_t PIT0MAP;
+ u_int8_t PIT1MAP;
+ u_int8_t PIT2MAP;
+ u_int8_t pad_0xd23[0x5];
+ u_int8_t UART1MAP;
+ u_int8_t UART2MAP;
+ u_int8_t pad_0xd2a[0x6];
+ u_int8_t PCIINTAMAP;
+ u_int8_t PCIINTBMAP;
+ u_int8_t PCIINTCMAP;
+ u_int8_t PCIINTDMAP;
+ u_int8_t pad_0xd34[0xc];
+ u_int8_t DMABCINTMAP;
+ u_int8_t SSIMAP;
+ u_int8_t WDTMAP;
+ u_int8_t RTCMAP;
+ u_int8_t WPVMAP;
+ u_int8_t ICEMAP;
+ u_int8_t FERRMAP;
+ u_int8_t pad_0xd47[0x9];
+ u_int8_t GP0IMAP;
+ u_int8_t GP1IMAP;
+ u_int8_t GP2IMAP;
+ u_int8_t GP3IMAP;
+ u_int8_t GP4IMAP;
+ u_int8_t GP5IMAP;
+ u_int8_t GP6IMAP;
+ u_int8_t GP7IMAP;
+ u_int8_t GP8IMAP;
+ u_int8_t GP9IMAP;
+ u_int8_t GP10IMAP;
+ u_int8_t pad_0xd5b[0x15];
+
+ /* Reset Generation */
+ u_int8_t SYSINFO;
+ u_int8_t pad_0xd71;
+ u_int8_t RESCFG;
+ u_int8_t pad_0xd73;
+ u_int8_t RESSTA;
+ u_int8_t pad_0xd75[0xb];
+
+ /* GP DMA Controller */
+ u_int8_t GPDMACTL;
+ u_int8_t GPDMAMMIO;
+ u_int16_t GPDMAEXTCHMAPA;
+ u_int16_t GPDMAEXTCHMAPB;
+ u_int8_t GPDMAEXTPG0;
+ u_int8_t GPDMAEXTPG1;
+ u_int8_t GPDMAEXTPG2;
+ u_int8_t GPDMAEXTPG3;
+ u_int8_t GPDMAEXTPG5;
+ u_int8_t GPDMAEXTPG6;
+ u_int8_t GPDMAEXTPG7;
+ u_int8_t pad_0xd8d[0x3];
+ u_int8_t GPDMAEXTTC3;
+ u_int8_t GPDMAEXTTC5;
+ u_int8_t GPDMAEXTTC6;
+ u_int8_t GPDMAEXTTC7;
+ u_int8_t pad_0xd94[0x4];
+ u_int8_t GPDMABCCTL;
+ u_int8_t GPDMABCSTA;
+ u_int8_t GPDMABSINTENB;
+ u_int8_t GPDMABCVAL;
+ u_int8_t pad_0xd9c[0x4];
+ u_int16_t GPDMANXTADDL3;
+ u_int16_t GPDMANXTADDH3;
+ u_int16_t GPDMANXTADDL5;
+ u_int16_t GPDMANXTADDH5;
+ u_int16_t GPDMANXTADDL6;
+ u_int16_t GPDMANXTADDH6;
+ u_int16_t GPDMANXTADDL7;
+ u_int16_t GPDMANXTADDH7;
+ u_int16_t GPDMANXTTCL3;
+ u_int8_t GPDMANXTTCH3;
+ u_int8_t pad_0xdb3;
+ u_int16_t GPDMANXTTCL5;
+ u_int8_t GPDMANXTTCH5;
+ u_int8_t pad_0xdb7;
+ u_int16_t GPDMANXTTCL6;
+ u_int8_t GPDMANXTTCH6;
+ u_int8_t pad_0xdbb;
+ u_int16_t GPDMANXTTCL7;
+ u_int8_t GPDMANXTTCH7;
+ u_int8_t pad_0xdc0[0x240];
+ };
+
+CTASSERT(sizeof(struct elan_mmcr) == 4096);
+
+extern volatile struct elan_mmcr * elan_mmcr;
+
+#endif /* _MACHINE_ELAN_MMCR_H_ */
diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h
index 78a4753e0a42..61da35981798 100644
--- a/sys/i386/include/md_var.h
+++ b/sys/i386/include/md_var.h
@@ -53,7 +53,6 @@ extern u_int cpu_id;
extern u_int cpu_procinfo;
extern char cpu_vendor[];
extern u_int cyrix_did;
-extern uint16_t *elan_mmcr;
extern char kstack[];
#ifdef PC98
extern int need_pre_dma_flush;