diff options
| author | Poul-Henning Kamp <phk@FreeBSD.org> | 2004-01-05 12:00:59 +0000 |
|---|---|---|
| committer | Poul-Henning Kamp <phk@FreeBSD.org> | 2004-01-05 12:00:59 +0000 |
| commit | 883bd55abd9f5910c6706cb8245bfdaf1d6ac356 (patch) | |
| tree | f18fcd1e48c29638fcdd4114e9a671971a5b6d39 | |
| parent | c2f1dd4d714cabc12822319e75bd5d6ac28e87b6 (diff) | |
Notes
| -rw-r--r-- | sys/i386/i386/elan-mmcr.c | 78 | ||||
| -rw-r--r-- | sys/i386/i386/vm_machdep.c | 10 | ||||
| -rw-r--r-- | sys/i386/include/elan_mmcr.h | 280 | ||||
| -rw-r--r-- | sys/i386/include/md_var.h | 1 |
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; |
