Add initialization code for the AMD Elan sc520 which maps the MMCR

into KVM and sets the i8254 frequency to the correct value.
This commit is contained in:
phk 2002-07-18 12:56:54 +00:00
parent a66125e62e
commit a1f0de15ca
8 changed files with 106 additions and 8 deletions

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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;

View File

@ -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";

View File

@ -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);
}

View File

@ -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_ */

View File

@ -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;

View File

@ -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";