- Apply 11_24_a_s1_core.diff from

https://openbios.org/roundup/linuxbios/issue24
- fix up for via epia-m



git-svn-id: svn://svn.coreboot.org/coreboot/trunk@2110 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
Stefan Reinauer 2005-11-26 16:56:05 +00:00
parent b7627bca65
commit f622d598db
14 changed files with 1073 additions and 15 deletions

View File

@ -7,6 +7,9 @@
* ACPI FADT, FACS, and DSDT table support added by
* Nick Barker <nick.barker9@btinternet.com>, and those portions
* (C) Copyright 2004 Nick Barker
*
* Copyright 2005 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
* 2005.9 yhlu add SRAT relate
*/
/*
@ -40,8 +43,10 @@ u8 acpi_checksum(u8 *table, u32 length)
void acpi_add_table(acpi_rsdt_t *rsdt, void *table)
{
int i;
for (i=0; i<8; i++) {
int entries_num = sizeof(rsdt->entry)/sizeof(rsdt->entry[0]);
for (i=0; i<entries_num; i++) {
if(rsdt->entry[i]==0) {
rsdt->entry[i]=(u32)table;
/* fix length to stop kernel winging about invalid entries */
@ -52,7 +57,7 @@ void acpi_add_table(acpi_rsdt_t *rsdt, void *table)
rsdt->header.checksum=acpi_checksum((u8 *)rsdt,
rsdt->header.length);
printk_debug("ACPI: added table %d/8 Length now %d\n",i+1,rsdt->header.length);
printk_debug("ACPI: added table %d/%d Length now %d\n",i+1, entries_num, rsdt->header.length);
return;
}
}
@ -133,7 +138,7 @@ void acpi_create_madt(acpi_madt_t *madt)
madt->lapic_addr= LOCAL_APIC_ADDR;
madt->flags = 0x1; /* PCAT_COMPAT */
current = acpi_dump_apics(current);
current = acpi_fill_madt(current);
/* recalculate length */
header->length= current - (unsigned long)madt;
@ -141,6 +146,63 @@ void acpi_create_madt(acpi_madt_t *madt)
header->checksum = acpi_checksum((void *)madt, header->length);
}
int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic)
{
lapic->type=0;
lapic->length=sizeof(acpi_srat_lapic_t);
lapic->flags=1;
lapic->proximity_domain_7_0 = node;
lapic->apic_id=apic;
return(lapic->length);
}
int acpi_create_srat_mem(acpi_srat_mem_t *mem, u8 node, u32 basek,u32 sizek, u32 flags)
{
mem->type=1;
mem->length=sizeof(acpi_srat_mem_t);
mem->base_address_low = (basek<<10);
mem->base_address_high = (basek>>(32-10));
mem->length_low = (sizek<<10);
mem->length_high = (sizek>>(32-10));
mem->proximity_domain = node;
mem->flags = flags;
return(mem->length);
}
void acpi_create_srat(acpi_srat_t *srat)
{
acpi_header_t *header=&(srat->header);
unsigned long current=(unsigned long)srat+sizeof(acpi_srat_t);
memset((void *)srat, 0, sizeof(acpi_srat_t));
/* fill out header fields */
memcpy(header->signature, SRAT_NAME, 4);
memcpy(header->oem_id, OEM_ID, 6);
memcpy(header->oem_table_id, SRAT_TABLE, 8);
memcpy(header->asl_compiler_id, ASLC, 4);
header->length = sizeof(acpi_srat_t);
header->revision = 1;
srat->resv = 0x1; /* BACK COMP */
current = acpi_fill_srat(current);
/* recalculate length */
header->length= current - (unsigned long)srat;
header->checksum = acpi_checksum((void *)srat, header->length);
}
void acpi_create_hpet(acpi_hpet_t *hpet)
{
#define HPET_ADDR 0xfed00000ULL

View File

@ -6,9 +6,12 @@
*
* The ACPI table structs are based on the Linux kernel sources.
*
*/
/* ACPI FADT & FACS added by Nick Barker <nick.barker9@btinternet.com>
* ACPI FADT & FACS added by Nick Barker <nick.barker9@btinternet.com>
* those parts (C) 2004 Nick Barker
*
* ACPI SRAT support 2005.9 yhlu add SRAT relate
* Copyright 2005 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
*
*/
@ -28,10 +31,12 @@ typedef unsigned long long u64;
#define RSDT_NAME "RSDT"
#define HPET_NAME "HPET"
#define MADT_NAME "APIC"
#define SRAT_NAME "SRAT"
#define RSDT_TABLE "RSDT "
#define HPET_TABLE "AMD64 "
#define MADT_TABLE "MADT "
#define SRAT_TABLE "SRAT "
#define OEM_ID "LXBIOS"
#define ASLC "NONE"
@ -79,13 +84,13 @@ typedef struct acpi_table_header /* ACPI common table header */
/* RSDT */
typedef struct acpi_rsdt {
struct acpi_table_header header;
u32 entry[8];
u32 entry[5+ACPI_SSDTX_NUM]; /* HPET, FADT, SRAT, MADT(APIC), SSDT, SSDTX */
} __attribute__ ((packed)) acpi_rsdt_t;
/* XSDT */
typedef struct acpi_xsdt {
struct acpi_table_header header;
u64 entry[8];
u64 entry[5+ACPI_SSDTX_NUM];
} __attribute__ ((packed)) acpi_xsdt_t;
@ -99,6 +104,43 @@ typedef struct acpi_hpet {
u8 attributes;
} __attribute__ ((packed)) acpi_hpet_t;
/* SRAT */
typedef struct acpi_srat {
struct acpi_table_header header;
u32 resv;
u64 resv1;
/* followed by static resource allocation structure[n]*/
} __attribute__ ((packed)) acpi_srat_t;
typedef struct acpi_srat_lapic {
u8 type;
u8 length;
u8 proximity_domain_7_0;
u8 apic_id;
u32 flags; /* enable bit 0 = 1, other bits reserved to 0 */
u8 local_sapic_eid;
u8 proximity_domain_31_8[3];
u32 resv;
} __attribute__ ((packed)) acpi_srat_lapic_t;
typedef struct acpi_srat_mem {
u8 type;
u8 length;
u32 proximity_domain;
u16 resv;
u32 base_address_low;
u32 base_address_high;
u32 length_low;
u32 length_high;
u32 resv1;
u32 flags; /* enable bit 0, hot pluggable bit 1; Non Volatile bit 2, other bits reserved */
u32 resv2[2];
} __attribute__ ((packed)) acpi_srat_mem_t;
/* MADT */
typedef struct acpi_madt {
struct acpi_table_header header;
u32 lapic_addr;
@ -152,6 +194,7 @@ typedef struct acpi_madt_irqoverride {
u16 flags;
} __attribute__ ((packed)) acpi_madt_irqoverride_t;
/* FADT */
typedef struct acpi_fadt {
struct acpi_table_header header;
@ -212,6 +255,7 @@ typedef struct acpi_fadt {
struct acpi_gen_regaddr x_gpe1_blk;
} __attribute__ ((packed)) acpi_fadt_t;
/* FACS */
typedef struct acpi_facs {
char signature[4];
u32 length;
@ -227,17 +271,35 @@ typedef struct acpi_facs {
/* These are implemented by the target port */
unsigned long write_acpi_tables(unsigned long addr);
unsigned long acpi_dump_apics(unsigned long current);
unsigned long acpi_fill_madt(unsigned long current);
unsigned long acpi_fill_srat(unsigned long current);
void acpi_create_fadt(acpi_fadt_t *fadt,acpi_facs_t *facs,void *dsdt);
/* These can be used by the target port */
u8 acpi_checksum(u8 *table, u32 length);
void acpi_add_table(acpi_rsdt_t *rsdt, void *table);
int acpi_create_madt_lapic(acpi_madt_lapic_t *lapic, u8 cpu, u8 apic);
int acpi_create_madt_ioapic(acpi_madt_ioapic_t *ioapic, u8 id, u32 addr,u32 gsi_base);
int acpi_create_madt_irqoverride(acpi_madt_irqoverride_t *irqoverride,
u8 bus, u8 source, u32 gsirq, u16 flags);
int acpi_create_madt_lapic_nmi(acpi_madt_lapic_nmi_t *lapic_nmi, u8 cpu,
u16 flags, u8 lint);
void acpi_create_madt(acpi_madt_t *madt);
unsigned long acpi_create_madt_lapics(unsigned long current);
unsigned long acpi_create_madt_lapic_nmis(unsigned long current, u16 flags, u8 lint);
int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic);
int acpi_create_srat_mem(acpi_srat_mem_t *mem, u8 node, u32 basek,u32 sizek, u32 flags);
unsigned long acpi_create_srat_lapics(unsigned long current);
void acpi_create_srat(acpi_srat_t *srat);
void acpi_create_hpet(acpi_hpet_t *hpet);
void acpi_create_facs(acpi_facs_t *facs);
void acpi_write_rsdt(acpi_rsdt_t *rsdt);
void acpi_write_rsdp(acpi_rsdp_t *rsdp, acpi_rsdt_t *rsdt);

View File

@ -778,6 +778,12 @@ define HAVE_ACPI_TABLES
comment "Define to build ACPI tables"
end
define ACPI_SSDTX_NUM
default 0
export always
comment "extra ssdt num for PCI Device"
end
define AGP_APERTURE_SIZE
default none
export used

View File

@ -49,10 +49,14 @@ void amd_sibling_init(device_t cpu, struct node_core_id id)
cpu_path.type = DEVICE_PATH_APIC;
cpu_path.u.apic.apic_id =
(0x10 + i*0x10 + id.nodeid);
new = alloc_dev(cpu->bus, &cpu_path);
if (!new) {
continue;
}
new->path.u.apic.node_id = cpu->path.u.apic.node_id;
new->path.u.apic.core_id = i;
/* Report what I have done */
printk_debug("CPU: %s %s\n",
dev_path(new), new->enabled?"enabled":"disabled");

View File

@ -38,6 +38,8 @@ struct i2c_path
struct apic_path
{
unsigned apic_id;
unsigned node_id;
unsigned core_id;
};
struct apic_cluster_path

View File

@ -13,11 +13,16 @@
extern unsigned char AmlCode[];
unsigned long acpi_dump_apics(unsigned long current)
unsigned long acpi_fill_madt(unsigned long current)
{
/* Nothing to do */
}
unsigned long acpi_fill_srat(unsigned long current)
{
/* No NUMA, no SRAT */
}
unsigned long write_acpi_tables(unsigned long start)
{
unsigned long current;

View File

@ -1,5 +1,7 @@
uses CONFIG_CHIP_NAME
uses AGP_APERTURE_SIZE
uses HAVE_ACPI_TABLES
default AGP_APERTURE_SIZE=0x4000000
if CONFIG_CHIP_NAME
@ -14,3 +16,9 @@ makerule raminit_test
depends "$(TOP)/src/northbridge/amd/amdk8/raminit.c"
action "$(HOSTCC) $(HOSTCFLAGS) $(CPUFLAGS) -Wno-unused-function -I$(TOP)/src/include -g $< -o $@"
end
if HAVE_ACPI_TABLES
object amdk8_acpi.o
end
object get_sblk_pci1234.o

View File

@ -0,0 +1,179 @@
/*============================================================================
Copyright 2005 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
This software and any related documentation (the "Materials") are the
confidential proprietary information of AMD. Unless otherwise provided in a
software agreement specifically licensing the Materials, the Materials are
provided in confidence and may not be distributed, modified, or reproduced in
whole or in part by any means.
LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY
EXPRESS OR IMPLIED WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO
WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY
PARTICULAR PURPOSE, OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR
USAGE OF TRADE. IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY
DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS,
BUSINESS INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR
INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION
OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
LIMITATION MAY NOT APPLY TO YOU.
AMD does not assume any responsibility for any errors which may appear in the
Materials nor any responsibility to support or update the Materials. AMD
retains the right to modify the Materials at any time, without notice, and is
not obligated to provide such modified Materials to you.
NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
further information, software, technical information, know-how, or show-how
available to you.
U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with "RESTRICTED
RIGHTS." Use, duplication, or disclosure by the Government is subject to the
restrictions as set forth in FAR 52.227-14 and DFAR 252.227-7013, et seq., or
its successor. Use of the Materials by the Government constitutes
acknowledgement of AMD's proprietary rights in them.
============================================================================*/
// 2005.9 serengeti support
// by yhlu
//
/*
* 2005.9 yhlu add madt lapic creat dynamically and SRAT related
*/
#include <console/console.h>
#include <string.h>
#include <arch/acpi.h>
#include <device/pci.h>
#include <cpu/x86/msr.h>
#include <cpu/amd/mtrr.h>
//it seems these function can be moved arch/i386/boot/acpi.c
unsigned long acpi_create_madt_lapics(unsigned long current)
{
device_t cpu;
int cpu_index = 0;
for(cpu = all_devices; cpu; cpu = cpu->next) {
if ((cpu->path.type != DEVICE_PATH_APIC) ||
(cpu->bus->dev->path.type != DEVICE_PATH_APIC_CLUSTER))
{
continue;
}
if (!cpu->enabled) {
continue;
}
current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current, cpu_index, cpu->path.u.apic.apic_id);
cpu_index++;
}
return current;
}
unsigned long acpi_create_madt_lapic_nmis(unsigned long current, u16 flags, u8 lint)
{
device_t cpu;
int cpu_index = 0;
for(cpu = all_devices; cpu; cpu = cpu->next) {
if ((cpu->path.type != DEVICE_PATH_APIC) ||
(cpu->bus->dev->path.type != DEVICE_PATH_APIC_CLUSTER))
{
continue;
}
if (!cpu->enabled) {
continue;
}
current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)current, cpu_index, flags, lint);
cpu_index++;
}
return current;
}
unsigned long acpi_create_srat_lapics(unsigned long current)
{
device_t cpu;
int cpu_index = 0;
for(cpu = all_devices; cpu; cpu = cpu->next) {
if ((cpu->path.type != DEVICE_PATH_APIC) ||
(cpu->bus->dev->path.type != DEVICE_PATH_APIC_CLUSTER))
{
continue;
}
if (!cpu->enabled) {
continue;
}
printk_debug("SRAT: lapic cpu_index=%02x, node_id=%02x, apic_id=%02x\n", cpu_index, cpu->path.u.apic.node_id, cpu->path.u.apic.apic_id);
current += acpi_create_srat_lapic((acpi_srat_lapic_t *)current, cpu->path.u.apic.node_id, cpu->path.u.apic.apic_id);
cpu_index++;
}
return current;
}
static unsigned long resk(uint64_t value)
{
unsigned long resultk;
if (value < (1ULL << 42)) {
resultk = value >> 10;
}
else {
resultk = 0xffffffff;
}
return resultk;
}
struct acpi_srat_mem_state {
unsigned long current;
};
void set_srat_mem(void *gp, struct device *dev, struct resource *res)
{
struct acpi_srat_mem_state *state = gp;
unsigned long basek, sizek;
basek = resk(res->base);
sizek = resk(res->size);
printk_debug("set_srat_mem: dev %s, res->index=%04x startk=%08x, sizek=%08x\n",
dev_path(dev), res->index, basek, sizek);
/*
0-640K must be on node 0
next range is from 1M---
So will cut off before 1M in the mem range
*/
if((basek+sizek)<1024) return;
if(basek<1024) {
sizek -= 1024 - basek;
basek = 1024;
}
state->current += acpi_create_srat_mem((acpi_srat_mem_t *)state->current, (res->index & 0xf), basek, sizek, 1); // need to figure out NV
}
unsigned long acpi_fill_srat(unsigned long current)
{
struct acpi_srat_mem_state srat_mem_state;
/* create all subtables for processors */
current = acpi_create_srat_lapics(current);
/* create all subteble for memory range */
/* 0-640K must be on node 0 */
current += acpi_create_srat_mem((acpi_srat_mem_t *)current, 0, 0, 640, 1);//enable
#if 1
srat_mem_state.current = current;
search_global_resources(
IORESOURCE_MEM | IORESOURCE_CACHEABLE, IORESOURCE_MEM | IORESOURCE_CACHEABLE,
set_srat_mem, &srat_mem_state);
current = srat_mem_state.current;
#endif
return current;
}
//end

View File

@ -0,0 +1,214 @@
/*============================================================================
Copyright 2005 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
This software and any related documentation (the "Materials") are the
confidential proprietary information of AMD. Unless otherwise provided in a
software agreement specifically licensing the Materials, the Materials are
provided in confidence and may not be distributed, modified, or reproduced in
whole or in part by any means.
LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY
EXPRESS OR IMPLIED WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO
WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY
PARTICULAR PURPOSE, OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR
USAGE OF TRADE. IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY
DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS,
BUSINESS INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR
INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION
OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
LIMITATION MAY NOT APPLY TO YOU.
AMD does not assume any responsibility for any errors which may appear in the
Materials nor any responsibility to support or update the Materials. AMD
retains the right to modify the Materials at any time, without notice, and is
not obligated to provide such modified Materials to you.
NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
further information, software, technical information, know-how, or show-how
available to you.
U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with "RESTRICTED
RIGHTS." Use, duplication, or disclosure by the Government is subject to the
restrictions as set forth in FAR 52.227-14 and DFAR 252.227-7013, et seq., or
its successor. Use of the Materials by the Government constitutes
acknowledgement of AMD's proprietary rights in them.
============================================================================*/
// 2005.9 serengeti support
// by yhlu
// 2005.9 yhlu modify that to more dynamic for AMD Opteron Based MB
#include <console/console.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <string.h>
#include <stdint.h>
#if 0
unsigned node_link_to_bus(unsigned node, unsigned link)
{
device_t dev;
unsigned reg;
dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
if (!dev) {
return 0;
}
for(reg = 0xE0; reg < 0xF0; reg += 0x04) {
uint32_t config_map;
unsigned dst_node;
unsigned dst_link;
unsigned bus_base;
config_map = pci_read_config32(dev, reg);
if ((config_map & 3) != 3) {
continue;
}
dst_node = (config_map >> 4) & 7;
dst_link = (config_map >> 8) & 3;
bus_base = (config_map >> 16) & 0xff;
#if 0
printk_debug("node.link=bus: %d.%d=%d 0x%2x->0x%08x\n",
dst_node, dst_link, bus_base,
reg, config_map);
#endif
if ((dst_node == node) && (dst_link == link))
{
return bus_base;
}
}
return 0;
}
#endif
extern unsigned pci1234[];
extern unsigned hc_possible_num;
extern unsigned sblk;
/* why we need pci1234 array
final result for pci1234 will be
pci1234[0] will record sblink and bus range
pci1234[i] will record ht chain i.
it will keep the sequence when some ht io card is not installed.
for Tyan S2885 the linxbios_ram will put 8151 chain (link 0) to 0xE0 reg, and 8131/8111 on 0xe4 reg, So we need to make sure the sb link
will always on pci1234[0]
for multi ht-io cards, if you don't install htio1, and only installed htio2, htio3, the htio will be on 0xe4, and 0xe8.
but we want to leave pci1234[1] to htio1 (even it is disabled) , and let htio2 and htio3 still use pci1234[2] and pci1234[3]
So we keep the sequence. ---- you need to preset the pci1234[1], pci1234[2], pci1234[3] for this purpose
for example you need set
unsigned pci1234[] = {
0x0000ff0,
0x0000f10, // HT IO 1 card always on node 1
0x0000f20, // HT IO 2 card always on node 2
0x0000f30 // HT IO 3 card always on node 3
};
for 2p+htio(n1)+htio(n0_1)+htio(n1_1),2p+htio(n1)+2p+htio(n2)+htio(n3) : need pci1234[6]
unsigned pci1234[] = {
0x0000ff0,
0x0000010, // HT IO 1 card always on node 1
0x0000f00, // HT IO 2 card always on node 0
0x0000110, // HT IO 3 card always on node 1
0x0000f20, // HT IO 4 card always on node 2
0x0000f30 // HT IO 5 card always on node 3
};
for 4p+htio(n1)+htio(n2)+htio(n3),4p+htio(n1)+4p+htio(n6)+htio(n7) : need pci1234[6]
unsigned pci1234[] = {
0x0000ff0,
0x0000f10, // HT IO 1 card always on node 1
0x0000f20, // HT IO 2 card always on node 2
0x0000f30, // HT IO 3 card always on node 3
0x0000f60, // HT IO 4 card always on node 6
0x0000f70 // HT IO 5 card always on node 7
};
for 2p+htio(n1)+htio(n0_1)+htio(n1_1), 2p+htio(n1)+2p+htio(n2)+htio(n3), 2p+htio(n1)+4p+htio(n4)+htio(n5), need pci1234[8]
unsigned pci1234[] = {
0x0000ff0,
0x0000010, // HT IO 1 card always on node 1
0x0000f00, // HT IO 2 card always on node 0
0x0000110, // HT IO 3 card always on node 1
0x0000f20, // HT IO 4 card always on node 2
0x0000f30 // HT IO 5 card always on node 3
0x0000f40, // HT IO 6 card always on node 4
0x0000f50 // HT IO 7 card always on node 5
};
for 4p+htio(n1)+htio(n2)+htio(n3), 4p+htio(n1)+2p+htio(n4)+htio(n5), 4p+htio(n1)+4p+htio(n6)+htio(n7), need pci1234[8]
unsigned pci1234[] = {
0x0000ff0,
0x0000f10, // HT IO 1 card always on node 1
0x0000f20, // HT IO 2 card always on node 2
0x0000f30, // HT IO 3 card always on node 3
0x0000f40, // HT IO 4 card always on node 4
0x0000f50 // HT IO 5 card always on node 5
0x0000f60, // HT IO 6 card always on node 6
0x0000f70 // HT IO 7 card always on node 7
};
So Max HC_POSSIBLE_NUM is 8
just put all the possible ht node/link to the list tp pci1234[] in get_bus_conf.c on MB dir
Also don't forget to increase the ACPI_SSDTX_NUM etc if you have too much SSDT
How about co-processor on socket 1 on 2 way system. or socket 2, and socket3 on 4 way system....? treat that as one hc too!
*/
void get_sblk_pci1234(void)
{
device_t dev;
int i,j;
uint32_t dword;
/* read PCI_DEV(0,0x18,0) 0x64 bit [8:9] to find out SbLink m */
dev = dev_find_slot(0, PCI_DEVFN(0x18,0));
dword = pci_read_config32(dev, 0x64);
sblk = (dword>>8) & 0x3;
dword &=0x0300;
dword |= 1;
pci1234[0] = dword;
/*about hardcode numbering for HT_IO support
set the node_id and link_id that could have ht chain in the one array,
then check if is enabled.... then update final value
*/
dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
for(j=0;j<4;j++) {
uint32_t dwordx;
dwordx = pci_read_config32(dev, 0xe0+j*4);
dwordx &=0xffff0ff1; //keep bus num, node_id, link_num, enable bits
if((dwordx & 0xff1) == dword) { //SBLINK
pci1234[0] = dwordx;
continue;
}
if((dwordx & 1) == 1) {
// We need to find out the number of HC
// for exact match
for(i=1;i<hc_possible_num;i++) {
if((dwordx & 0xff0) == (pci1234[i] & 0xff0)) {
pci1234[i] = dwordx;
break;
}
}
// for 0xff0 match or same node
for(i=1;i<hc_possible_num;i++) {
if((dwordx & 0xff0) == (dwordx & pci1234[i] & 0xff0)) {
pci1234[i] = dwordx;
break;
}
}
}
}
for(i=1;i<hc_possible_num;i++) {
if((pci1234[i] & 1) != 1) {
pci1234[i] = 0;
}
}
}

View File

@ -692,7 +692,7 @@ static void pci_domain_set_resources(device_t dev)
/* Round mmio_basek to something the processor can support */
mmio_basek &= ~((1 << 6) -1);
idx = 10;
idx = 0x10;
for(i = 0; i < 8; i++) {
uint32_t base, limit;
unsigned basek, limitk, sizek;
@ -708,7 +708,8 @@ static void pci_domain_set_resources(device_t dev)
/* see if we need a hole from 0xa0000 to 0xbffff */
if ((basek < ((8*64)+(8*16))) && (sizek > ((8*64)+(16*16)))) {
ram_resource(dev, idx++, basek, ((8*64)+(8*16)) - basek);
ram_resource(dev, (idx | i), basek, ((8*64)+(8*16)) - basek);
idx += 0x10;
basek = (8*64)+(16*16);
sizek = limitk - ((8*64)+(16*16));
@ -720,7 +721,8 @@ static void pci_domain_set_resources(device_t dev)
if (basek < mmio_basek) {
unsigned pre_sizek;
pre_sizek = mmio_basek - basek;
ram_resource(dev, idx++, basek, pre_sizek);
ram_resource(dev, (idx | i), basek, pre_sizek);
idx += 0x10;
sizek -= pre_sizek;
if(! is_cpu_pre_e0() ) {
sizek += hoist_memory(mmio_basek,i);
@ -735,7 +737,8 @@ static void pci_domain_set_resources(device_t dev)
sizek -= (4*1024*1024 - mmio_basek);
}
}
ram_resource(dev, idx++, basek, sizek);
ram_resource(dev, (idx | i), basek, sizek);
idx += 0x10;
}
assign_resources(&dev->link[0]);
}
@ -838,6 +841,8 @@ static unsigned int cpu_bus_scan(device_t dev, unsigned int max)
/* Report what I have done */
if (cpu) {
cpu->path.u.apic.node_id = i;
cpu->path.u.apic.core_id = 0;
printk_debug("CPU: %s %s\n",
dev_path(cpu), cpu->enabled?"enabled":"disabled");
}

View File

@ -66,6 +66,10 @@ static int lsmbus_write_byte(device_t dev, uint8_t address, uint8_t val)
return do_smbus_write_byte(res->base, device, address, val);
}
#if HAVE_ACPI_TABLES == 1
unsigned pm_base;
#endif
static void acpi_init(struct device *dev)
{
uint8_t byte;
@ -129,6 +133,12 @@ static void acpi_init(struct device *dev)
printk_debug("Throttling CPU %2d.%1.1d percent.\n",
(on*12)+(on>>1),(on&1)*5);
}
#if HAVE_ACPI_TABLES == 1
pm_base = pci_read_config16(dev, 0x58) & 0xff00;
printk_debug("pm_base: 0x%04x\n",pm_base);
#endif
}
static void acpi_read_resources(device_t dev)

View File

@ -0,0 +1 @@
driver amd8132_bridge.o

View File

@ -0,0 +1,457 @@
/*============================================================================
Copyright 2005 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
This software and any related documentation (the "Materials") are the
confidential proprietary information of AMD. Unless otherwise provided in a
software agreement specifically licensing the Materials, the Materials are
provided in confidence and may not be distributed, modified, or reproduced in
whole or in part by any means.
LIMITATION OF LIABILITY: THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY
EXPRESS OR IMPLIED WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO
WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY
PARTICULAR PURPOSE, OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR
USAGE OF TRADE. IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY
DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS,
BUSINESS INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR
INABILITY TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE EXCLUSION
OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
LIMITATION MAY NOT APPLY TO YOU.
AMD does not assume any responsibility for any errors which may appear in the
Materials nor any responsibility to support or update the Materials. AMD
retains the right to modify the Materials at any time, without notice, and is
not obligated to provide such modified Materials to you.
NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
further information, software, technical information, know-how, or show-how
available to you.
U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with "RESTRICTED
RIGHTS." Use, duplication, or disclosure by the Government is subject to the
restrictions as set forth in FAR 52.227-14 and DFAR 252.227-7013, et seq., or
its successor. Use of the Materials by the Government constitutes
acknowledgement of AMD's proprietary rights in them.
============================================================================*/
//@DOC
// in amd8132_bridge.c
/*
$1.0$
*/
// Description: amd 8132 support
// by yhlu
//
//============================================================================
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <pc80/mc146818rtc.h>
#include <device/pci_def.h>
#include <device/pcix.h>
#define NMI_OFF 0
#define NPUML 0xD9 /* Non prefetchable upper memory limit */
#define NPUMB 0xD8 /* Non prefetchable upper memory base */
static void amd8132_walk_children(struct bus *bus,
void (*visit)(device_t dev, void *ptr), void *ptr)
{
device_t child;
for(child = bus->children; child; child = child->sibling)
{
if (child->path.type != DEVICE_PATH_PCI) {
continue;
}
if (child->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
amd8132_walk_children(&child->link[0], visit, ptr);
}
visit(child, ptr);
}
}
struct amd8132_bus_info {
unsigned sstatus;
unsigned rev;
int master_devices;
int max_func;
};
static void amd8132_count_dev(device_t dev, void *ptr)
{
struct amd8132_bus_info *info = ptr;
/* Don't count pci bridges */
if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
info->master_devices++;
}
if (PCI_FUNC(dev->path.u.pci.devfn) > info->max_func) {
info->max_func = PCI_FUNC(dev->path.u.pci.devfn);
}
}
static void amd8132_pcix_tune_dev(device_t dev, void *ptr)
{
struct amd8132_bus_info *info = ptr;
unsigned cap;
unsigned status, cmd, orig_cmd;
unsigned max_read, max_tran;
int sibs;
if (dev->hdr_type != PCI_HEADER_TYPE_NORMAL) {
return;
}
cap = pci_find_capability(dev, PCI_CAP_ID_PCIX);
if (!cap) {
return;
}
/* How many siblings does this device have? */
sibs = info->master_devices - 1;
printk_debug("%s AMD8132 PCI-X tuning\n", dev_path(dev));
status = pci_read_config32(dev, cap + PCI_X_STATUS);
orig_cmd = cmd = pci_read_config16(dev,cap + PCI_X_CMD);
max_read = (status & PCI_X_STATUS_MAX_READ) >> 21;
max_tran = (status & PCI_X_STATUS_MAX_SPLIT) >> 23;
if (info->rev == 0x01) { // only a1 need it
/* Errata #53 Limit the number of split transactions to avoid starvation */
if (sibs >= 2) {
/* At most 2 outstanding split transactions when we have
* 3 or more bus master devices on the bus.
*/
if (max_tran > 1) {
max_tran = 1;
}
}
else if (sibs == 1) {
/* At most 4 outstanding split transactions when we have
* 2 bus master devices on the bus.
*/
if (max_tran > 3) {
max_tran = 3;
}
}
else {
/* At most 8 outstanding split transactions when we have
* only one bus master device on the bus.
*/
if (max_tran > 4) {
max_tran = 4;
}
}
}
if (max_read != ((cmd & PCI_X_CMD_MAX_READ) >> 2)) {
cmd &= ~PCI_X_CMD_MAX_READ;
cmd |= max_read << 2;
}
if (max_tran != ((cmd & PCI_X_CMD_MAX_SPLIT) >> 4)) {
cmd &= ~PCI_X_CMD_MAX_SPLIT;
cmd |= max_tran << 4;
}
/* Don't attempt to handle PCI-X errors */
cmd &= ~PCI_X_CMD_DPERR_E;
if (orig_cmd != cmd) {
pci_write_config16(dev, cap + PCI_X_CMD, cmd);
}
}
static unsigned int amd8132_scan_bus(struct bus *bus,
unsigned min_devfn, unsigned max_devfn, unsigned int max)
{
struct amd8132_bus_info info;
unsigned pos;
/* Find the children on the bus */
max = pci_scan_bus(bus, min_devfn, max_devfn, max);
/* Find the revision of the 8132 */
info.rev = pci_read_config8(bus->dev, PCI_CLASS_REVISION);
/* Find the pcix capability and get the secondary bus status */
pos = pci_find_capability(bus->dev, PCI_CAP_ID_PCIX);
info.sstatus = pci_read_config16(bus->dev, pos + PCI_X_SEC_STATUS);
/* Print the PCI-X bus speed */
printk_debug("PCI: %02x: %s sstatus=%04x rev=%02x \n", bus->secondary, pcix_speed(info.sstatus), info.sstatus, info.rev);
/* Examine the bus and find out how loaded it is */
info.max_func = 0;
info.master_devices = 0;
amd8132_walk_children(bus, amd8132_count_dev, &info);
#if 0
/* Disable the bus if there are no devices on it
*/
if (!bus->children)
{
unsigned pcix_misc;
/* Disable all of my children */
disable_children(bus);
/* Remember the device is disabled */
bus->dev->enabled = 0;
/* Disable the PCI-X clocks */
pcix_misc = pci_read_config32(bus->dev, 0x40);
pcix_misc &= ~(0x1f << 16);
pci_write_config32(bus->dev, 0x40, pcix_misc);
return max;
}
#endif
/* If we are in conventional PCI mode nothing more is necessary.
*/
if (PCI_X_SSTATUS_MFREQ(info.sstatus) == PCI_X_SSTATUS_CONVENTIONAL_PCI) {
return max;
}
/* Tune the devices on the bus */
amd8132_walk_children(bus, amd8132_pcix_tune_dev, &info);
return max;
}
static unsigned int amd8132_scan_bridge(device_t dev, unsigned int max)
{
return do_pci_scan_bridge(dev, max, amd8132_scan_bus);
}
static void amd8132_pcix_init(device_t dev)
{
uint32_t dword;
uint8_t byte;
unsigned chip_rev;
/* Find the revision of the 8132 */
chip_rev = pci_read_config8(dev, PCI_CLASS_REVISION);
/* Enable memory write and invalidate ??? */
dword = pci_read_config32(dev, 0x04);
dword |= 0x10;
dword &= ~(1<<6); // PERSP Parity Error Response
pci_write_config32(dev, 0x04, dword);
if (chip_rev == 0x01) {
/* Errata #37 */
byte = pci_read_config8(dev, 0x0c);
if(byte == 0x08 )
pci_write_config8(dev, 0x0c, 0x10);
#if 0
/* Errata #59*/
dword = pci_read_config32(dev, 0x40);
dword &= ~(1<<31);
pci_write_config32(dev, 0x40, dword);
#endif
}
/* Set up error reporting, enable all */
/* system error enable */
dword = pci_read_config32(dev, 0x04);
dword |= (1<<8);
pci_write_config32(dev, 0x04, dword);
/* system and error parity enable */
dword = pci_read_config32(dev, 0x3c);
dword |= (3<<16);
pci_write_config32(dev, 0x3c, dword);
dword = pci_read_config32(dev, 0x40);
// dword &= ~(1<<31); /* WriteChainEnable */
dword |= (1<<31);
dword |= (1<<7);// must set to 1
dword |= (3<<21); //PCIErrorSerrDisable
pci_write_config32(dev, 0x40, dword);
/* EXTARB = 1, COMPAT = 0 */
dword = pci_read_config32(dev, 0x48);
dword |= (1<<3);
dword &= ~(1<<0);
dword |= (1<<15); //CLEARPCILOG_L
dword |= (1<<19); //PERR FATAL Enable
dword |= (1<<22); // SERR FATAL Enable
dword |= (1<<23); // LPMARBENABLE
dword |= (0x61<<24); //LPMARBCOUNT
pci_write_config32(dev, 0x48, dword);
dword = pci_read_config32(dev, 0x4c);
dword |= (1<<6); //intial prefetch for memory read line request
dword |= (1<<9); //continuous prefetch Enable for memory read line request
pci_write_config32(dev, 0x4c, dword);
/* Disable Single-Bit-Error Correction [30] = 0 */
dword = pci_read_config32(dev, 0x70);
dword &= ~(1<<30);
pci_write_config32(dev, 0x70, dword);
//link
dword = pci_read_config32(dev, 0xd4);
dword |= (0x5c<<16);
pci_write_config32(dev, 0xd4, dword);
/* TxSlack0 [16:17] = 0, RxHwLookahdEn0 [18] = 1, TxSlack1 [24:25] = 0, RxHwLookahdEn1 [26] = 1 */
dword = pci_read_config32(dev, 0xdc);
dword |= (1<<1) | (1<<4); // stream disable 1 to 0 , DBLINSRATE
dword |= (1<<18)|(1<<26);
dword &= ~((3<<16)|(3<<24));
pci_write_config32(dev, 0xdc, dword);
/* Set up CRC flood enable */
dword = pci_read_config32(dev, 0xc0);
if(dword) { /* do device A only */
#if 0
dword = pci_read_config32(dev, 0xc4);
dword |= (1<<1);
pci_write_config32(dev, 0xc4, dword);
dword = pci_read_config32(dev, 0xc8);
dword |= (1<<1);
pci_write_config32(dev, 0xc8, dword);
#endif
if (chip_rev == 0x11) {
/* [18] Clock Gate Enable = 1 */
dword = pci_read_config32(dev, 0xf0);
dword |= 0x00040008;
pci_write_config32(dev, 0xf0, dword);
}
}
return;
}
#define BRIDGE_40_BIT_SUPPORT 0
#if BRIDGE_40_BIT_SUPPORT
static void bridge_read_resources(struct device *dev)
{
struct resource *res;
pci_bus_read_resources(dev);
res = find_resource(dev, PCI_MEMORY_BASE);
if (res) {
res->limit = 0xffffffffffULL;
}
}
static void bridge_set_resources(struct device *dev)
{
struct resource *res;
res = find_resource(dev, PCI_MEMORY_BASE);
if (res) {
resource_t base, end;
/* set the memory range */
dev->command |= PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
res->flags |= IORESOURCE_STORED;
compute_allocate_resource(&dev->link[0], res,
IORESOURCE_MEM | IORESOURCE_PREFETCH,
IORESOURCE_MEM);
base = res->base;
end = resource_end(res);
pci_write_config16(dev, PCI_MEMORY_BASE, base >> 16);
pci_write_config8(dev, NPUML, (base >> 32) & 0xff);
pci_write_config16(dev, PCI_MEMORY_LIMIT, end >> 16);
pci_write_config8(dev, NPUMB, (end >> 32) & 0xff);
report_resource_stored(dev, res, "");
}
pci_dev_set_resources(dev);
}
#endif /* BRIDGE_40_BIT_SUPPORT */
static struct device_operations pcix_ops = {
#if BRIDGE_40_BIT_SUPPORT
.read_resources = bridge_read_resources,
.set_resources = bridge_set_resources,
#else
.read_resources = pci_bus_read_resources,
.set_resources = pci_dev_set_resources,
#endif
.enable_resources = pci_bus_enable_resources,
.init = amd8132_pcix_init,
.scan_bus = amd8132_scan_bridge,
.reset_bus = pci_bus_reset,
};
static struct pci_driver pcix_driver __pci_driver = {
.ops = &pcix_ops,
.vendor = PCI_VENDOR_ID_AMD,
.device = 0x7458,
};
static void ioapic_enable(device_t dev)
{
uint32_t value;
value = pci_read_config32(dev, 0x44);
if (dev->enabled) {
value |= ((1 << 1) | (1 << 0));
} else {
value &= ~((1 << 1) | (1 << 0));
}
pci_write_config32(dev, 0x44, value);
}
static void amd8132_ioapic_init(device_t dev)
{
uint32_t dword;
unsigned chip_rev;
/* Find the revision of the 8132 */
chip_rev = pci_read_config8(dev, PCI_CLASS_REVISION);
if (chip_rev == 0x01) {
#if 0
/* Errata #43 */
dword = pci_read_config32(dev, 0xc8);
dword |= (0x3<<23);
pci_write_config32(dev, 0xc8, dword);
#endif
}
if( (chip_rev == 0x11) ||(chip_rev == 0x12) ) {
//for b1 b2
/* Errata #73 */
dword = pci_read_config32(dev, 0x80);
dword |= (0x1f<<5);
pci_write_config32(dev, 0x80, dword);
dword = pci_read_config32(dev, 0x88);
dword |= (0x1f<<5);
pci_write_config32(dev, 0x88, dword);
/* Errata #74 */
dword = pci_read_config32(dev, 0x7c);
dword &= ~(0x3<<30);
dword |= (0x01<<30);
pci_write_config32(dev, 0x7c, dword);
}
}
static struct pci_operations pci_ops_pci_dev = {
.set_subsystem = pci_dev_set_subsystem,
};
static struct device_operations ioapic_ops = {
.read_resources = pci_dev_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = amd8132_ioapic_init,
.scan_bus = 0,
.enable = ioapic_enable,
.ops_pci = &pci_ops_pci_dev,
};
static struct pci_driver ioapic_driver __pci_driver = {
.ops = &ioapic_ops,
.vendor = PCI_VENDOR_ID_AMD,
.device = 0x7459,
};

View File

@ -0,0 +1,43 @@
# abuild config file for EPIA-M
target via_epia-m
mainboard via/epia-m
option MAXIMUM_CONSOLE_LOGLEVEL=8
option DEFAULT_CONSOLE_LOGLEVEL=8
option CONFIG_CONSOLE_SERIAL8250=1
option ROM_SIZE=524288
option HAVE_OPTION_TABLE=1
option CONFIG_ROM_STREAM=1
option HAVE_FALLBACK_BOOT=1
###
### Compute the location and size of where this firmware image
### (linuxBIOS plus bootloader) will live in the boot rom chip.
###
option FALLBACK_SIZE=131072
## LinuxBIOS C code runs at this location in RAM
option _RAMBASE=0x00004000
#
# Via EPIA M
#
romimage "normal"
option USE_FALLBACK_IMAGE=0
option ROM_IMAGE_SIZE=0x10000
option LINUXBIOS_EXTRA_VERSION=".0-Normal"
payload /dev/null
end
romimage "fallback"
option USE_FALLBACK_IMAGE=1
option ROM_IMAGE_SIZE=0x10000
option LINUXBIOS_EXTRA_VERSION=".0-Fallback"
payload /dev/null
end
buildrom ./linuxbios.rom ROM_SIZE "normal" "fallback"