diff options
author | phk <phk@FreeBSD.org> | 2002-07-18 12:56:54 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2002-07-18 12:56:54 +0000 |
commit | a535ae674163bf2e4c7e82bad38f699906bc0286 (patch) | |
tree | 7f65914b2426cd2a843193bdbdbd650cfaf0ecef | |
parent | 22ef5eeda558acdeccae3ce8719709218305667c (diff) | |
download | FreeBSD-src-a535ae674163bf2e4c7e82bad38f699906bc0286.zip FreeBSD-src-a535ae674163bf2e4c7e82bad38f699906bc0286.tar.gz |
Add initialization code for the AMD Elan sc520 which maps the MMCR
into KVM and sets the i8254 frequency to the correct value.
-rw-r--r-- | sys/amd64/amd64/identcpu.c | 53 | ||||
-rw-r--r-- | sys/amd64/include/cputypes.h | 1 | ||||
-rw-r--r-- | sys/amd64/include/md_var.h | 1 | ||||
-rw-r--r-- | sys/amd64/pci/pci_bus.c | 2 | ||||
-rw-r--r-- | sys/i386/i386/identcpu.c | 53 | ||||
-rw-r--r-- | sys/i386/include/cputypes.h | 1 | ||||
-rw-r--r-- | sys/i386/include/md_var.h | 1 | ||||
-rw-r--r-- | sys/i386/pci/pci_bus.c | 2 |
8 files changed, 106 insertions, 8 deletions
diff --git a/sys/amd64/amd64/identcpu.c b/sys/amd64/amd64/identcpu.c index 47d10ff..a195fcf 100644 --- a/sys/amd64/amd64/identcpu.c +++ b/sys/amd64/amd64/identcpu.c @@ -262,14 +262,16 @@ printcpuinfo(void) strcat(cpu_model, "Standard Am486DX"); break; case 0x430: - strcat(cpu_model, "Am486DX2/4 Write-Through"); + strcat(cpu_model, "Enhanced Am486DX2 Write-Through"); break; case 0x470: - case 0x490: - strcat(cpu_model, "Enhanced Am486DX4 Write-Back"); + strcat(cpu_model, "Enhanced Am486DX2 Write-Back"); break; case 0x480: - strcat(cpu_model, "Enhanced Am486DX4 Write-Through"); + strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Through"); + break; + case 0x490: + strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Back"); break; case 0x4E0: strcat(cpu_model, "Am5x86 Write-Through"); @@ -1325,3 +1327,46 @@ print_transmeta_info() crusoe_frequency, crusoe_voltage, crusoe_percentage); } +/* + * The AMD Elan sc520 is a system-on-chip gadget which is used in embedded + * kind of things, see www.soekris.com for instance, and it has a few quirks + * we need to deal with. + * Unfortunately we cannot identify the gadget by CPUID output because it + * depends on strapping options and only the stepping field may be useful + * and those are undocumented from AMDs side. + * + * So instead we recognize the on-chip host-PCI bridge and call back from + * sys/i386/pci/pci_bus.c to here if we find it. + */ + +#include <sys/proc.h> +#include <vm/vm.h> +#include <vm/pmap.h> + +u_char *elan_mmcr; + +void +init_AMD_Elan_sc520(void) +{ + u_int new; + int i; + + printf("Doing h0h0magic for AMD Elan sc520\n"); + elan_mmcr = pmap_mapdev(0xfffef000, 0x1000); + printf("MMCR at %p\n", elan_mmcr); + + /*- + * The i8254 is driven with a nonstandard frequency which is + * derived thusly: + * f = 32768 * 45 * 25 / 31 = 1189161.29... + * We use the sysctl to get the timecounter etc into whack. + */ + + new = 1189161; + i = kernel_sysctlbyname(&thread0, "machdep.i8254_freq", + NULL, 0, + &new, sizeof new, + NULL); + printf("sysctl machdep.i8254_freq=%d returns %d\n", new, i); +} + diff --git a/sys/amd64/include/cputypes.h b/sys/amd64/include/cputypes.h index 585df67..999b174 100644 --- a/sys/amd64/include/cputypes.h +++ b/sys/amd64/include/cputypes.h @@ -68,6 +68,7 @@ struct cpu_nameclass { extern int cpu; extern int cpu_class; +void init_AMD_Elan_sc520(void); #endif #endif /* !_MACHINE_CPUTYPES_H_ */ diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index 041362f..e75994e 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -48,6 +48,7 @@ extern u_int cpu_id; extern u_int cpu_fxsr; extern char cpu_vendor[]; extern u_int cyrix_did; +extern u_char *elan_mmcr; extern char kstack[]; #ifdef PC98 extern int need_pre_dma_flush; diff --git a/sys/amd64/pci/pci_bus.c b/sys/amd64/pci/pci_bus.c index 4e325b2..65ba7d3 100644 --- a/sys/amd64/pci/pci_bus.c +++ b/sys/amd64/pci/pci_bus.c @@ -40,6 +40,7 @@ #include <machine/nexusvar.h> #include <machine/pci_cfgreg.h> #include <machine/segments.h> +#include <machine/cputypes.h> #include <machine/pc/bios.h> #include "pcib_if.h" @@ -177,6 +178,7 @@ nexus_pcib_is_host_bridge(int bus, int slot, int func, /* AMD -- vendor 0x1022 */ case 0x30001022: s = "AMD Elan SC520 host to PCI bridge"; + init_AMD_Elan_sc520(); break; case 0x70061022: s = "AMD-751 host to PCI bridge"; diff --git a/sys/i386/i386/identcpu.c b/sys/i386/i386/identcpu.c index 47d10ff..a195fcf 100644 --- a/sys/i386/i386/identcpu.c +++ b/sys/i386/i386/identcpu.c @@ -262,14 +262,16 @@ printcpuinfo(void) strcat(cpu_model, "Standard Am486DX"); break; case 0x430: - strcat(cpu_model, "Am486DX2/4 Write-Through"); + strcat(cpu_model, "Enhanced Am486DX2 Write-Through"); break; case 0x470: - case 0x490: - strcat(cpu_model, "Enhanced Am486DX4 Write-Back"); + strcat(cpu_model, "Enhanced Am486DX2 Write-Back"); break; case 0x480: - strcat(cpu_model, "Enhanced Am486DX4 Write-Through"); + strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Through"); + break; + case 0x490: + strcat(cpu_model, "Enhanced Am486DX4/Am5x86 Write-Back"); break; case 0x4E0: strcat(cpu_model, "Am5x86 Write-Through"); @@ -1325,3 +1327,46 @@ print_transmeta_info() crusoe_frequency, crusoe_voltage, crusoe_percentage); } +/* + * The AMD Elan sc520 is a system-on-chip gadget which is used in embedded + * kind of things, see www.soekris.com for instance, and it has a few quirks + * we need to deal with. + * Unfortunately we cannot identify the gadget by CPUID output because it + * depends on strapping options and only the stepping field may be useful + * and those are undocumented from AMDs side. + * + * So instead we recognize the on-chip host-PCI bridge and call back from + * sys/i386/pci/pci_bus.c to here if we find it. + */ + +#include <sys/proc.h> +#include <vm/vm.h> +#include <vm/pmap.h> + +u_char *elan_mmcr; + +void +init_AMD_Elan_sc520(void) +{ + u_int new; + int i; + + printf("Doing h0h0magic for AMD Elan sc520\n"); + elan_mmcr = pmap_mapdev(0xfffef000, 0x1000); + printf("MMCR at %p\n", elan_mmcr); + + /*- + * The i8254 is driven with a nonstandard frequency which is + * derived thusly: + * f = 32768 * 45 * 25 / 31 = 1189161.29... + * We use the sysctl to get the timecounter etc into whack. + */ + + new = 1189161; + i = kernel_sysctlbyname(&thread0, "machdep.i8254_freq", + NULL, 0, + &new, sizeof new, + NULL); + printf("sysctl machdep.i8254_freq=%d returns %d\n", new, i); +} + diff --git a/sys/i386/include/cputypes.h b/sys/i386/include/cputypes.h index 585df67..999b174 100644 --- a/sys/i386/include/cputypes.h +++ b/sys/i386/include/cputypes.h @@ -68,6 +68,7 @@ struct cpu_nameclass { extern int cpu; extern int cpu_class; +void init_AMD_Elan_sc520(void); #endif #endif /* !_MACHINE_CPUTYPES_H_ */ diff --git a/sys/i386/include/md_var.h b/sys/i386/include/md_var.h index 041362f..e75994e 100644 --- a/sys/i386/include/md_var.h +++ b/sys/i386/include/md_var.h @@ -48,6 +48,7 @@ extern u_int cpu_id; extern u_int cpu_fxsr; extern char cpu_vendor[]; extern u_int cyrix_did; +extern u_char *elan_mmcr; extern char kstack[]; #ifdef PC98 extern int need_pre_dma_flush; diff --git a/sys/i386/pci/pci_bus.c b/sys/i386/pci/pci_bus.c index 4e325b2..65ba7d3 100644 --- a/sys/i386/pci/pci_bus.c +++ b/sys/i386/pci/pci_bus.c @@ -40,6 +40,7 @@ #include <machine/nexusvar.h> #include <machine/pci_cfgreg.h> #include <machine/segments.h> +#include <machine/cputypes.h> #include <machine/pc/bios.h> #include "pcib_if.h" @@ -177,6 +178,7 @@ nexus_pcib_is_host_bridge(int bus, int slot, int func, /* AMD -- vendor 0x1022 */ case 0x30001022: s = "AMD Elan SC520 host to PCI bridge"; + init_AMD_Elan_sc520(); break; case 0x70061022: s = "AMD-751 host to PCI bridge"; |