sizeram removal/conversion.
- mem.h and sizeram.h and all includes killed because the are no longer needed. - linuxbios_table.c updated to directly look at the device tree for occupied memory areas. - first very incomplete stab a converting the ppc code to work with the dynamic device tree - Ignore resources before we have read them from devices, (if the device is disabled ignore it's resources). - First stab at Pentium-M support - add part/init_timer.h making init_timer conditional until there is a better way of handling it. - Converted all of the x86 sizeram to northbridge set_resources functions. git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1722 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
This commit is contained in:
parent
20fc678d65
commit
6e53f50082
|
@ -1,5 +1,4 @@
|
|||
#include <console/console.h>
|
||||
#include <mem.h>
|
||||
#include <ip_checksum.h>
|
||||
#include <boot/linuxbios_tables.h>
|
||||
#include "linuxbios_table.h"
|
||||
|
@ -8,7 +7,6 @@
|
|||
#include <device/device.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
struct lb_header *lb_table_init(unsigned long addr)
|
||||
{
|
||||
struct lb_header *header;
|
||||
|
@ -130,11 +128,8 @@ void lb_strings(struct lb_header *header)
|
|||
|
||||
}
|
||||
|
||||
/* Some version of gcc have problems with 64 bit types so
|
||||
* take an unsigned long instead of a uint64_t for now.
|
||||
*/
|
||||
void lb_memory_range(struct lb_memory *mem,
|
||||
uint32_t type, unsigned long start, unsigned long size)
|
||||
uint32_t type, uint64_t start, uint64_t size)
|
||||
{
|
||||
int entries;
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
|
@ -144,19 +139,6 @@ void lb_memory_range(struct lb_memory *mem,
|
|||
mem->size += sizeof(mem->map[0]);
|
||||
}
|
||||
|
||||
static void lb_memory_rangek(struct lb_memory *mem,
|
||||
uint32_t type, unsigned long startk, unsigned long endk)
|
||||
{
|
||||
int entries;
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
mem->map[entries].start = startk;
|
||||
mem->map[entries].start <<= 10;
|
||||
mem->map[entries].size = endk - startk;
|
||||
mem->map[entries].size <<= 10;
|
||||
mem->map[entries].type = type;
|
||||
mem->size += sizeof(mem->map[0]);
|
||||
}
|
||||
|
||||
static void lb_reserve_table_memory(struct lb_header *head)
|
||||
{
|
||||
struct lb_record *last_rec;
|
||||
|
@ -189,7 +171,6 @@ static void lb_reserve_table_memory(struct lb_header *head)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned long lb_table_fini(struct lb_header *head)
|
||||
{
|
||||
struct lb_record *rec, *first_rec;
|
||||
|
@ -207,6 +188,112 @@ unsigned long lb_table_fini(struct lb_header *head)
|
|||
return (unsigned long)rec;
|
||||
}
|
||||
|
||||
static void lb_cleanup_memory_ranges(struct lb_memory *mem)
|
||||
{
|
||||
int entries;
|
||||
int i, j;
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
|
||||
/* Sort the lb memory ranges */
|
||||
for(i = 0; i < entries; i++) {
|
||||
for(j = i; j < entries; j++) {
|
||||
if (mem->map[j].start < mem->map[i].start) {
|
||||
struct lb_memory_range tmp;
|
||||
tmp = mem->map[i];
|
||||
mem->map[i] = mem->map[j];
|
||||
mem->map[j] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Merge adjacent entries */
|
||||
for(i = 0; (i + 1) < entries; i++) {
|
||||
uint64_t start, end, nstart, nend;
|
||||
if (mem->map[i].type != mem->map[i + 1].type) {
|
||||
continue;
|
||||
}
|
||||
start = mem->map[i].start;
|
||||
end = start + mem->map[i].size;
|
||||
nstart = mem->map[i + 1].start;
|
||||
nend = nstart + mem->map[i + 1].size;
|
||||
if ((start <= nstart) && (end > nstart)) {
|
||||
if (start > nstart) {
|
||||
start = nstart;
|
||||
}
|
||||
if (end < nend) {
|
||||
end = nend;
|
||||
}
|
||||
/* Record the new region size */
|
||||
mem->map[i].start = start;
|
||||
mem->map[i].size = end - start;
|
||||
|
||||
/* Delete the entry I have merged with */
|
||||
memmove(&mem->map[i + 1], &mem->map[i + 2],
|
||||
((entries - i - 2) * sizeof(mem->map[0])));
|
||||
mem->size -= sizeof(mem->map[0]);
|
||||
entries -= 1;
|
||||
/* See if I can merge with the next entry as well */
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lb_remove_memory_range(struct lb_memory *mem,
|
||||
uint64_t start, uint64_t size)
|
||||
{
|
||||
uint64_t end;
|
||||
int entries;
|
||||
int i;
|
||||
|
||||
end = start + size;
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
|
||||
/* Remove a reserved area from the memory map */
|
||||
for(i = 0; i < entries; i++) {
|
||||
uint64_t map_start = mem->map[i].start;
|
||||
uint64_t map_end = map_start + mem->map[i].size;
|
||||
if ((start <= map_start) && (end >= map_end)) {
|
||||
/* Remove the completely covered range */
|
||||
memmove(&mem->map[i], &mem->map[i + 1],
|
||||
((entries - i - 1) * sizeof(mem->map[0])));
|
||||
mem->size -= sizeof(mem->map[0]);
|
||||
entries -= 1;
|
||||
/* Since the index will disappear revisit what will appear here */
|
||||
i -= 1;
|
||||
}
|
||||
else if ((start > map_start) && (end < map_end)) {
|
||||
/* Split the memory range */
|
||||
memmove(&mem->map[i + 1], &mem->map[i],
|
||||
((entries - i) * sizeof(mem->map[0])));
|
||||
mem->size += sizeof(mem->map[0]);
|
||||
entries += 1;
|
||||
/* Update the first map entry */
|
||||
mem->map[i].size = start - map_start;
|
||||
/* Update the second map entry */
|
||||
mem->map[i + 1].start = end;
|
||||
mem->map[i + 1].size = map_end - end;
|
||||
/* Don't bother with this map entry again */
|
||||
i += 1;
|
||||
}
|
||||
else if ((start <= map_start) && (end > map_start)) {
|
||||
/* Shrink the start of the memory range */
|
||||
mem->map[i].start = end;
|
||||
mem->map[i].size = map_end - end;
|
||||
}
|
||||
else if ((start < map_end) && (start > map_start)) {
|
||||
/* Shrink the end of the memory range */
|
||||
mem->map[i].size = start - map_start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lb_add_memory_range(struct lb_memory *mem,
|
||||
uint32_t type, uint64_t start, uint64_t size)
|
||||
{
|
||||
lb_remove_memory_range(mem, start, size);
|
||||
lb_memory_range(mem, type, start, size);
|
||||
lb_cleanup_memory_ranges(mem);
|
||||
}
|
||||
|
||||
/* Routines to extract part so the linuxBIOS table or
|
||||
* information from the linuxBIOS table after we have written it.
|
||||
|
@ -219,61 +306,28 @@ struct lb_memory *get_lb_mem(void)
|
|||
return mem_ranges;
|
||||
}
|
||||
|
||||
struct mem_range *sizeram(void)
|
||||
static struct lb_memory *build_lb_mem(struct lb_header *head)
|
||||
{
|
||||
struct mem_range *mem, *rmem;
|
||||
struct lb_memory *mem;
|
||||
struct device *dev;
|
||||
unsigned int count;
|
||||
count = 0;
|
||||
for(dev = all_devices; dev; dev = dev->next) {
|
||||
struct resource *res, *last;
|
||||
last = &dev->resource[dev->resources];
|
||||
for(res = &dev->resource[0]; res < last; res++) {
|
||||
if ((res->flags & IORESOURCE_MEM) &&
|
||||
(res->flags & IORESOURCE_CACHEABLE))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
rmem = mem = malloc(sizeof(*mem) * (count + 1));
|
||||
for(dev = all_devices; dev; dev = dev->next) {
|
||||
struct resource *res, *last;
|
||||
last = &dev->resource[dev->resources];
|
||||
for(res = &dev->resource[0]; res < last; res++) {
|
||||
if ((res->flags & IORESOURCE_MEM) &&
|
||||
(res->flags & IORESOURCE_CACHEABLE))
|
||||
{
|
||||
mem->basek = res->base >> 10;
|
||||
mem->sizek = res->size >> 10;
|
||||
mem++;
|
||||
}
|
||||
}
|
||||
}
|
||||
mem->basek = 0;
|
||||
mem->sizek = 0;
|
||||
#if 0
|
||||
for(mem = rmem; mem->sizek; mem++) {
|
||||
printk_debug("basek: %lu sizek: %lu\n",
|
||||
mem->basek, mem->sizek);
|
||||
}
|
||||
#endif
|
||||
return rmem;
|
||||
}
|
||||
|
||||
static struct mem_range *get_ramsize(void)
|
||||
{
|
||||
struct mem_range *mem = 0;
|
||||
if (!mem) {
|
||||
mem = sizeram();
|
||||
}
|
||||
if (!mem) {
|
||||
printk_emerg("No memory size information!\n");
|
||||
for(;;) {
|
||||
/* Ensure this loop is not optimized away */
|
||||
asm volatile("":/* outputs */:/*inputs */ :"memory");
|
||||
/* Record where the lb memory ranges will live */
|
||||
mem = lb_memory(head);
|
||||
mem_ranges = mem;
|
||||
|
||||
/* Build the raw table of memory */
|
||||
for(dev = all_devices; dev; dev = dev->next) {
|
||||
struct resource *res, *last;
|
||||
last = &dev->resource[dev->resources];
|
||||
for(res = &dev->resource[0]; res < last; res++) {
|
||||
if (!(res->flags & IORESOURCE_MEM) ||
|
||||
!(res->flags & IORESOURCE_CACHEABLE)) {
|
||||
continue;
|
||||
}
|
||||
lb_memory_range(mem, LB_MEM_RAM, res->base, res->size);
|
||||
}
|
||||
}
|
||||
lb_cleanup_memory_ranges(mem);
|
||||
return mem;
|
||||
}
|
||||
|
||||
|
@ -282,51 +336,38 @@ unsigned long write_linuxbios_table(
|
|||
unsigned long rom_table_startk, unsigned long rom_table_endk)
|
||||
{
|
||||
unsigned long table_size;
|
||||
struct mem_range *ram, *ramp;
|
||||
struct lb_header *head;
|
||||
struct lb_memory *mem;
|
||||
struct lb_record *rec_dest, *rec_src;
|
||||
|
||||
ram = get_ramsize();
|
||||
head = lb_table_init(low_table_end);
|
||||
low_table_end = (unsigned long)head;
|
||||
#if HAVE_OPTION_TABLE == 1
|
||||
/* Write the option config table... */
|
||||
rec_dest = lb_new_record(head);
|
||||
rec_src = (struct lb_record *)&option_table;
|
||||
memcpy(rec_dest, rec_src, rec_src->size);
|
||||
#endif
|
||||
mem = lb_memory(head);
|
||||
mem_ranges = mem;
|
||||
/* I assume there is always ram at address 0 */
|
||||
/* Reserve our tables in low memory */
|
||||
table_size = (low_table_end - low_table_start);
|
||||
lb_memory_range(mem, LB_MEM_TABLE, 0, table_size);
|
||||
lb_memory_range(mem, LB_MEM_RAM, table_size, (ram[0].sizek << 10) - table_size);
|
||||
/* Reserving pci memory mapped space will keep the kernel from booting seeing
|
||||
* any pci resources.
|
||||
*/
|
||||
for(ramp = &ram[1]; ramp->sizek; ramp++) {
|
||||
unsigned long startk, endk;
|
||||
startk = ramp->basek;
|
||||
endk = startk + ramp->sizek;
|
||||
if ((startk < rom_table_startk) && (endk > rom_table_startk)) {
|
||||
lb_memory_rangek(mem, LB_MEM_RAM, startk, rom_table_startk);
|
||||
startk = rom_table_startk;
|
||||
}
|
||||
if ((startk == rom_table_startk) && (endk > startk)) {
|
||||
unsigned long tend;
|
||||
tend = rom_table_endk;
|
||||
if (tend > endk) {
|
||||
tend = endk;
|
||||
}
|
||||
lb_memory_rangek(mem, LB_MEM_TABLE, rom_table_startk, tend);
|
||||
startk = tend;
|
||||
}
|
||||
if (endk > startk) {
|
||||
lb_memory_rangek(mem, LB_MEM_RAM, startk, endk);
|
||||
}
|
||||
if (HAVE_OPTION_TABLE == 1) {
|
||||
struct lb_record *rec_dest, *rec_src;
|
||||
/* Write the option config table... */
|
||||
rec_dest = lb_new_record(head);
|
||||
rec_src = (struct lb_record *)&option_table;
|
||||
memcpy(rec_dest, rec_src, rec_src->size);
|
||||
}
|
||||
/* Record where RAM is located */
|
||||
mem = build_lb_mem(head);
|
||||
|
||||
/* Find the current mptable size */
|
||||
table_size = (low_table_end - low_table_start);
|
||||
|
||||
/* Record the mptable and the the lb_table (This will be adjusted later) */
|
||||
lb_add_memory_range(mem, LB_MEM_TABLE,
|
||||
low_table_start, table_size);
|
||||
|
||||
/* Record the pirq table */
|
||||
lb_add_memory_range(mem, LB_MEM_TABLE,
|
||||
rom_table_startk << 10, (rom_table_endk - rom_table_startk) << 10);
|
||||
|
||||
/* Note:
|
||||
* I assume that there is always memory at immediately after
|
||||
* the low_table_end. This means that after I setup the linuxbios table.
|
||||
* I can trivially fixup the reserved memory ranges to hold the correct
|
||||
* size of the linuxbios table.
|
||||
*/
|
||||
|
||||
/* Record our motheboard */
|
||||
lb_mainboard(head);
|
||||
|
|
|
@ -15,7 +15,7 @@ struct lb_record *lb_next_record(struct lb_record *rec);
|
|||
struct lb_record *lb_new_record(struct lb_header *header);
|
||||
struct lb_memory *lb_memory(struct lb_header *header);
|
||||
void lb_memory_range(struct lb_memory *mem,
|
||||
uint32_t type, unsigned long startk, unsigned long sizek);
|
||||
uint32_t type, uint64_t start, uint64_t size);
|
||||
struct lb_mainboard *lb_mainboard(struct lb_header *header);
|
||||
unsigned long lb_table_fini(struct lb_header *header);
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
#include <console/console.h>
|
||||
#include <mem.h>
|
||||
#include <ip_checksum.h>
|
||||
#include <boot/linuxbios_tables.h>
|
||||
#include "linuxbios_table.h"
|
||||
#include <string.h>
|
||||
#include <version.h>
|
||||
|
||||
#include <device/device.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct lb_header *lb_table_init(unsigned long addr)
|
||||
{
|
||||
|
@ -128,11 +128,8 @@ void lb_strings(struct lb_header *header)
|
|||
|
||||
}
|
||||
|
||||
/* Some version of gcc have problems with 64 bit types so
|
||||
* take an unsigned long instead of a uint64_t for now.
|
||||
*/
|
||||
void lb_memory_range(struct lb_memory *mem,
|
||||
uint32_t type, unsigned long start, unsigned long size)
|
||||
uint32_t type, uint64_t start, uint64_t size)
|
||||
{
|
||||
int entries;
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
|
@ -142,19 +139,6 @@ void lb_memory_range(struct lb_memory *mem,
|
|||
mem->size += sizeof(mem->map[0]);
|
||||
}
|
||||
|
||||
static void lb_memory_rangek(struct lb_memory *mem,
|
||||
uint32_t type, unsigned long startk, unsigned long endk)
|
||||
{
|
||||
int entries;
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
mem->map[entries].start = startk;
|
||||
mem->map[entries].start <<= 10;
|
||||
mem->map[entries].size = endk - startk;
|
||||
mem->map[entries].size <<= 10;
|
||||
mem->map[entries].type = type;
|
||||
mem->size += sizeof(mem->map[0]);
|
||||
}
|
||||
|
||||
static void lb_reserve_table_memory(struct lb_header *head)
|
||||
{
|
||||
struct lb_record *last_rec;
|
||||
|
@ -187,7 +171,6 @@ static void lb_reserve_table_memory(struct lb_header *head)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned long lb_table_fini(struct lb_header *head)
|
||||
{
|
||||
struct lb_record *rec, *first_rec;
|
||||
|
@ -205,6 +188,112 @@ unsigned long lb_table_fini(struct lb_header *head)
|
|||
return (unsigned long)rec;
|
||||
}
|
||||
|
||||
static void lb_cleanup_memory_ranges(struct lb_memory *mem)
|
||||
{
|
||||
int entries;
|
||||
int i, j;
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
|
||||
/* Sort the lb memory ranges */
|
||||
for(i = 0; i < entries; i++) {
|
||||
for(j = i; j < entries; j++) {
|
||||
if (mem->map[j].start < mem->map[i].start) {
|
||||
struct lb_memory_range tmp;
|
||||
tmp = mem->map[i];
|
||||
mem->map[i] = mem->map[j];
|
||||
mem->map[j] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Merge adjacent entries */
|
||||
for(i = 0; (i + 1) < entries; i++) {
|
||||
uint64_t start, end, nstart, nend;
|
||||
if (mem->map[i].type != mem->map[i + 1].type) {
|
||||
continue;
|
||||
}
|
||||
start = mem->map[i].start;
|
||||
end = start + mem->map[i].size;
|
||||
nstart = mem->map[i + 1].start;
|
||||
nend = nstart + mem->map[i + 1].size;
|
||||
if ((start <= nstart) && (end > nstart)) {
|
||||
if (start > nstart) {
|
||||
start = nstart;
|
||||
}
|
||||
if (end < nend) {
|
||||
end = nend;
|
||||
}
|
||||
/* Record the new region size */
|
||||
mem->map[i].start = start;
|
||||
mem->map[i].size = end - start;
|
||||
|
||||
/* Delete the entry I have merged with */
|
||||
memmove(&mem->map[i + 1], &mem->map[i + 2],
|
||||
((entries - i - 2) * sizeof(mem->map[0])));
|
||||
mem->size -= sizeof(mem->map[0]);
|
||||
entries -= 1;
|
||||
/* See if I can merge with the next entry as well */
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lb_remove_memory_range(struct lb_memory *mem,
|
||||
uint64_t start, uint64_t size)
|
||||
{
|
||||
uint64_t end;
|
||||
int entries;
|
||||
int i;
|
||||
|
||||
end = start + size;
|
||||
entries = (mem->size - sizeof(*mem))/sizeof(mem->map[0]);
|
||||
|
||||
/* Remove a reserved area from the memory map */
|
||||
for(i = 0; i < entries; i++) {
|
||||
uint64_t map_start = mem->map[i].start;
|
||||
uint64_t map_end = map_start + mem->map[i].size;
|
||||
if ((start <= map_start) && (end >= map_end)) {
|
||||
/* Remove the completely covered range */
|
||||
memmove(&mem->map[i], &mem->map[i + 1],
|
||||
((entries - i - 1) * sizeof(mem->map[0])));
|
||||
mem->size -= sizeof(mem->map[0]);
|
||||
entries -= 1;
|
||||
/* Since the index will disappear revisit what will appear here */
|
||||
i -= 1;
|
||||
}
|
||||
else if ((start > map_start) && (end < map_end)) {
|
||||
/* Split the memory range */
|
||||
memmove(&mem->map[i + 1], &mem->map[i],
|
||||
((entries - i) * sizeof(mem->map[0])));
|
||||
mem->size += sizeof(mem->map[0]);
|
||||
entries += 1;
|
||||
/* Update the first map entry */
|
||||
mem->map[i].size = start - map_start;
|
||||
/* Update the second map entry */
|
||||
mem->map[i + 1].start = end;
|
||||
mem->map[i + 1].size = map_end - end;
|
||||
/* Don't bother with this map entry again */
|
||||
i += 1;
|
||||
}
|
||||
else if ((start <= map_start) && (end > map_start)) {
|
||||
/* Shrink the start of the memory range */
|
||||
mem->map[i].start = end;
|
||||
mem->map[i].size = map_end - end;
|
||||
}
|
||||
else if ((start < map_end) && (start > map_start)) {
|
||||
/* Shrink the end of the memory range */
|
||||
mem->map[i].size = start - map_start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void lb_add_memory_range(struct lb_memory *mem,
|
||||
uint32_t type, uint64_t start, uint64_t size)
|
||||
{
|
||||
lb_remove_memory_range(mem, start, size);
|
||||
lb_memory_range(mem, type, start, size);
|
||||
lb_cleanup_memory_ranges(mem);
|
||||
}
|
||||
|
||||
/* Routines to extract part so the linuxBIOS table or
|
||||
* information from the linuxBIOS table after we have written it.
|
||||
|
@ -217,58 +306,68 @@ struct lb_memory *get_lb_mem(void)
|
|||
return mem_ranges;
|
||||
}
|
||||
|
||||
static struct lb_memory *build_lb_mem(struct lb_header *head)
|
||||
{
|
||||
struct lb_memory *mem;
|
||||
struct device *dev;
|
||||
|
||||
/* Record where the lb memory ranges will live */
|
||||
mem = lb_memory(head);
|
||||
mem_ranges = mem;
|
||||
|
||||
/* Build the raw table of memory */
|
||||
for(dev = all_devices; dev; dev = dev->next) {
|
||||
struct resource *res, *last;
|
||||
last = &dev->resource[dev->resources];
|
||||
for(res = &dev->resource[0]; res < last; res++) {
|
||||
if (!(res->flags & IORESOURCE_MEM) ||
|
||||
!(res->flags & IORESOURCE_CACHEABLE)) {
|
||||
continue;
|
||||
}
|
||||
lb_memory_range(mem, LB_MEM_RAM, res->base, res->size);
|
||||
}
|
||||
}
|
||||
lb_cleanup_memory_ranges(mem);
|
||||
return mem;
|
||||
}
|
||||
|
||||
unsigned long write_linuxbios_table(
|
||||
struct mem_range *ram,
|
||||
unsigned long low_table_start, unsigned long low_table_end,
|
||||
unsigned long rom_table_startk, unsigned long rom_table_endk)
|
||||
{
|
||||
unsigned long table_size;
|
||||
struct mem_range *ramp;
|
||||
struct lb_header *head;
|
||||
struct lb_memory *mem;
|
||||
#if HAVE_OPTION_TABLE == 1
|
||||
struct lb_record *rec_dest, *rec_src;
|
||||
#endif
|
||||
|
||||
head = lb_table_init(low_table_end);
|
||||
low_table_end = (unsigned long)head;
|
||||
#if HAVE_OPTION_TABLE == 1
|
||||
/* Write the option config table... */
|
||||
rec_dest = lb_new_record(head);
|
||||
rec_src = (struct lb_record *)&option_table;
|
||||
memcpy(rec_dest, rec_src, rec_src->size);
|
||||
#endif
|
||||
mem = lb_memory(head);
|
||||
mem_ranges = mem;
|
||||
/* I assume there is always ram at address 0 */
|
||||
/* Reserve our tables in low memory */
|
||||
table_size = (low_table_end - low_table_start);
|
||||
lb_memory_range(mem, LB_MEM_TABLE, 0, table_size);
|
||||
lb_memory_range(mem, LB_MEM_RAM, table_size, (ram[0].sizek << 10) - table_size);
|
||||
/* Reserving pci memory mapped space will keep the kernel from booting seeing
|
||||
* any pci resources.
|
||||
*/
|
||||
for(ramp = &ram[1]; ramp->sizek; ramp++) {
|
||||
unsigned long startk, endk;
|
||||
startk = ramp->basek;
|
||||
endk = startk + ramp->sizek;
|
||||
if ((startk < rom_table_startk) && (endk > rom_table_startk)) {
|
||||
lb_memory_rangek(mem, LB_MEM_RAM, startk, rom_table_startk);
|
||||
startk = rom_table_startk;
|
||||
}
|
||||
if ((startk == rom_table_startk) && (endk > startk)) {
|
||||
unsigned long tend;
|
||||
tend = rom_table_endk;
|
||||
if (tend > endk) {
|
||||
tend = endk;
|
||||
}
|
||||
lb_memory_rangek(mem, LB_MEM_TABLE, rom_table_startk, tend);
|
||||
startk = tend;
|
||||
}
|
||||
if (endk > startk) {
|
||||
lb_memory_rangek(mem, LB_MEM_RAM, startk, endk);
|
||||
}
|
||||
if (HAVE_OPTION_TABLE == 1) {
|
||||
struct lb_record *rec_dest, *rec_src;
|
||||
/* Write the option config table... */
|
||||
rec_dest = lb_new_record(head);
|
||||
rec_src = (struct lb_record *)&option_table;
|
||||
memcpy(rec_dest, rec_src, rec_src->size);
|
||||
}
|
||||
/* Record where RAM is located */
|
||||
mem = build_lb_mem(head);
|
||||
|
||||
/* Find the current mptable size */
|
||||
table_size = (low_table_end - low_table_start);
|
||||
|
||||
/* Record the mptable and the the lb_table (This will be adjusted later) */
|
||||
lb_add_memory_range(mem, LB_MEM_TABLE,
|
||||
low_table_start, table_size);
|
||||
|
||||
/* Record the pirq table */
|
||||
lb_add_memory_range(mem, LB_MEM_TABLE,
|
||||
rom_table_startk << 10, (rom_table_endk - rom_table_startk) << 10);
|
||||
|
||||
/* Note:
|
||||
* I assume that there is always memory at immediately after
|
||||
* the low_table_end. This means that after I setup the linuxbios table.
|
||||
* I can trivially fixup the reserved memory ranges to hold the correct
|
||||
* size of the linuxbios table.
|
||||
*/
|
||||
|
||||
/* Record our motheboard */
|
||||
lb_mainboard(head);
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#include <console/console.h>
|
||||
#include <mem.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <boot/tables.h>
|
||||
#include <boot/linuxbios_tables.h>
|
||||
#include "linuxbios_table.h"
|
||||
|
||||
struct lb_memory *
|
||||
write_tables(struct mem_range *mem)
|
||||
write_tables(void)
|
||||
{
|
||||
unsigned long low_table_start, low_table_end;
|
||||
unsigned long rom_table_start, rom_table_end;
|
||||
|
@ -20,7 +19,7 @@ write_tables(struct mem_range *mem)
|
|||
low_table_end = 16;
|
||||
|
||||
/* The linuxbios table must be in 0-4K or 960K-1M */
|
||||
write_linuxbios_table(mem,
|
||||
write_linuxbios_table(
|
||||
low_table_start, low_table_end,
|
||||
rom_table_start >> 10, rom_table_end >> 10);
|
||||
|
||||
|
|
|
@ -1,35 +1,49 @@
|
|||
#include <console/console.h>
|
||||
#include <mem.h>
|
||||
#include <arch/io.h>
|
||||
#include <string.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <cpu/ppc/cpuid.h>
|
||||
#include <smp/start_stop.h>
|
||||
#include "ppc.h"
|
||||
#include "ppcreg.h"
|
||||
|
||||
static void cache_on(struct mem_range *mem)
|
||||
{
|
||||
}
|
||||
#error "FIXME what should call cpu_initialize?"
|
||||
|
||||
static void interrupts_on()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long cpu_initialize(struct mem_range *mem)
|
||||
void cpu_initialize(void)
|
||||
{
|
||||
/* Because we busy wait at the printk spinlock.
|
||||
* It is important to keep the number of printed messages
|
||||
* from secondary cpus to a minimum, when debugging is
|
||||
* disabled.
|
||||
*/
|
||||
unsigned long processor_id = this_processors_id();
|
||||
printk_notice("Initializing CPU #%d\n", processor_id);
|
||||
struct device *cpu;
|
||||
struct cpu_info *info;
|
||||
info = cpu_info();
|
||||
|
||||
printk_notice("Initializing CPU #%d\n", info->index);
|
||||
|
||||
cpu = info->cpu;
|
||||
if (!cpu) {
|
||||
die("CPU: missing cpu device structure");
|
||||
}
|
||||
|
||||
/* Find what type of cpu we are dealing with */
|
||||
cpu->vendor 0; /* PPC cpus do not have a vendor field */
|
||||
cpu->device = ppc_getpvr();
|
||||
display_cpuid(cpu);
|
||||
|
||||
#if 0
|
||||
/* Lookup the cpu's operations */
|
||||
set_cpu_ops(cpu);
|
||||
|
||||
/* Initialize the cpu */
|
||||
if (cpu->ops && cpu->ops->init) {
|
||||
cpu->enabled = 1;
|
||||
cpu->initialized = 1;
|
||||
cpu->ops->init();
|
||||
}
|
||||
#endif
|
||||
/* Turn on caching if we haven't already */
|
||||
cache_on(mem);
|
||||
|
||||
display_cpuid();
|
||||
|
||||
interrupts_on();
|
||||
|
||||
printk_info("CPU #%d Initialized\n", processor_id);
|
||||
return processor_id;
|
||||
|
|
|
@ -5,62 +5,62 @@
|
|||
#include "ppcreg.h"
|
||||
#include <console/console.h>
|
||||
|
||||
void display_cpuid(void)
|
||||
void display_cpuid(struct device *cpu)
|
||||
{
|
||||
unsigned type = ppc_getpvr() >> 16;
|
||||
unsigned version = ppc_getpvr() & 0xffff;
|
||||
const char *cpu_string = 0;
|
||||
switch(type) {
|
||||
unsigned type = cpu->device >> 16;
|
||||
unsigned version = cpu->device & 0xffff;
|
||||
const char *cpu_string = 0;
|
||||
switch(type) {
|
||||
case 0x0001:
|
||||
cpu_string = "601";
|
||||
break;
|
||||
cpu_string = "601";
|
||||
break;
|
||||
case 0x0003:
|
||||
cpu_string = "603";
|
||||
break;
|
||||
cpu_string = "603";
|
||||
break;
|
||||
case 0x0004:
|
||||
cpu_string = "604";
|
||||
break;
|
||||
cpu_string = "604";
|
||||
break;
|
||||
case 0x0006:
|
||||
cpu_string = "603e";
|
||||
break;
|
||||
cpu_string = "603e";
|
||||
break;
|
||||
case 0x0007:
|
||||
cpu_string = "603ev";
|
||||
break;
|
||||
cpu_string = "603ev";
|
||||
break;
|
||||
case 0x0008:
|
||||
cpu_string = "750";
|
||||
break;
|
||||
cpu_string = "750";
|
||||
break;
|
||||
case 0x0009:
|
||||
cpu_string = "604e";
|
||||
break;
|
||||
cpu_string = "604e";
|
||||
break;
|
||||
case 0x000a:
|
||||
cpu_string = "604ev5 (MachV)";
|
||||
break;
|
||||
cpu_string = "604ev5 (MachV)";
|
||||
break;
|
||||
case 0x000c:
|
||||
cpu_string = "7400";
|
||||
break;
|
||||
cpu_string = "7400";
|
||||
break;
|
||||
case 0x0032:
|
||||
cpu_string = "821";
|
||||
break;
|
||||
cpu_string = "821";
|
||||
break;
|
||||
case 0x0050:
|
||||
cpu_string = "860";
|
||||
break;
|
||||
cpu_string = "860";
|
||||
break;
|
||||
case 0x4011:
|
||||
cpu_string = "405GP";
|
||||
break;
|
||||
cpu_string = "405GP";
|
||||
break;
|
||||
case 0x5091:
|
||||
cpu_string = "405GPr";
|
||||
break;
|
||||
cpu_string = "405GPr";
|
||||
break;
|
||||
case 0x5121:
|
||||
cpu_string = "405EP";
|
||||
break;
|
||||
cpu_string = "405EP";
|
||||
break;
|
||||
case 0x800c:
|
||||
cpu_string = "7410";
|
||||
break;
|
||||
}
|
||||
if (cpu_string)
|
||||
printk_info("PowerPC %s", cpu_string);
|
||||
else
|
||||
printk_info("PowerPC unknown (0x%x)", type);
|
||||
printk_info(" CPU, version %d.%d\n", version >> 8, version & 0xff);
|
||||
cpu_string = "7410";
|
||||
break;
|
||||
}
|
||||
if (cpu_string)
|
||||
printk_info("PowerPC %s", cpu_string);
|
||||
else
|
||||
printk_info("PowerPC unknown (0x%x)", type);
|
||||
printk_info(" CPU, version %d.%d\n", version >> 8, version & 0xff);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ it with the version available from LANL.
|
|||
|
||||
|
||||
#include <console/console.h>
|
||||
#include <mem.h>
|
||||
#include <version.h>
|
||||
#include <boot/tables.h>
|
||||
#include <device/device.h>
|
||||
|
@ -35,6 +34,7 @@ it with the version available from LANL.
|
|||
#include <delay.h>
|
||||
#include <stdlib.h>
|
||||
#include <part/hard_reset.h>
|
||||
#include <part/init_timer.h>
|
||||
#include <boot/elf.h>
|
||||
|
||||
void hardwaremain(int boot_complete)
|
||||
|
|
|
@ -702,6 +702,11 @@ end
|
|||
# Misc options
|
||||
###############################################
|
||||
|
||||
define HAVE_INIT_TIMER
|
||||
default 0
|
||||
export always
|
||||
comment "Have a init_timer function"
|
||||
end
|
||||
define HAVE_HARD_RESET
|
||||
default none
|
||||
export used
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
uses HAVE_INIT_TIMER
|
||||
default HAVE_INIT_TIMER=1
|
||||
dir /cpu/x86/tsc
|
||||
dir /cpu/x86/fpu
|
||||
dir /cpu/x86/mmx
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
uses CONFIG_UDELAY_TSC
|
||||
uses CONFIG_TSC_X86RDTSC_CALIBRATE_WITH_TIMER2
|
||||
uses HAVE_INIT_TIMER
|
||||
|
||||
default CONFIG_TSC_X86RDTSC_CALIBRATE_WITH_TIMER2=0
|
||||
if CONFIG_UDELAY_TSC object delay_tsc.o end
|
||||
if CONFIG_UDELAY_TSC
|
||||
default HAVE_INIT_TIMER=1
|
||||
object delay_tsc.o
|
||||
end
|
||||
|
|
|
@ -203,6 +203,8 @@ static void find_largest_resource(struct pick_largest_state *state,
|
|||
struct device *curdev;
|
||||
for(curdev = bus->children; curdev; curdev = curdev->sibling) {
|
||||
int i;
|
||||
/* Ignore disabled devices */
|
||||
if (!curdev->have_resources) continue;
|
||||
for(i = 0; i < curdev->resources; i++) {
|
||||
struct resource *resource = &curdev->resource[i];
|
||||
/* If it isn't the right kind of resource ignore it */
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
#ifndef MEM_H
|
||||
#define MEM_H
|
||||
|
||||
struct mem_range {
|
||||
unsigned long basek;
|
||||
unsigned long sizek;
|
||||
};
|
||||
|
||||
/* mem_range arrays are non-overlapping, in ascending order and null terminated */
|
||||
|
||||
struct mem_range *sizeram(void);
|
||||
|
||||
#endif /* MEM_H */
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#ifndef ASSEMBLY
|
||||
|
||||
#if HAVE_FALLBACK_BOOT
|
||||
#if HAVE_FALLBACK_BOOT == 1
|
||||
void boot_successful(void);
|
||||
#else
|
||||
#define boot_successful()
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef PART_INIT_TIMER_H
|
||||
#define PART_DELAY_H
|
||||
|
||||
#if HAVE_INIT_TIMER == 1
|
||||
void init_timer(void);
|
||||
#else
|
||||
#define init_timer() do{} while(0)
|
||||
#endif
|
||||
|
||||
#endif /* PART_INIT_TIMER_H */
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef PART_SIZERAM_H
|
||||
#define PART_SIZERAM_H
|
||||
|
||||
struct mem_rang;
|
||||
struct mem_range *sizeram(void);
|
||||
|
||||
#endif /* PART_SIZERAM_H */
|
|
@ -45,7 +45,7 @@ uses DEFAULT_CONSOLE_LOGLEVEL
|
|||
uses MAXIMUM_CONSOLE_LOGLEVEL
|
||||
uses MAINBOARD_POWER_ON_AFTER_POWER_FAIL
|
||||
uses CONFIG_CONSOLE_SERIAL8250
|
||||
|
||||
uses HAVE_INIT_TIMER
|
||||
|
||||
###
|
||||
### Build options
|
||||
|
|
|
@ -165,6 +165,7 @@ static void main(unsigned long bist)
|
|||
amd_early_mtrr_init();
|
||||
enable_lapic();
|
||||
init_timer();
|
||||
/* Has this cpu already booted? */
|
||||
if (cpu_init_detected()) {
|
||||
asm volatile ("jmp __cpu_reset");
|
||||
}
|
||||
|
|
|
@ -202,9 +202,12 @@ end
|
|||
##
|
||||
## Setup RAM
|
||||
##
|
||||
mainboardinit cpu/p6/enable_mmx_sse.inc
|
||||
mainboardinit cpu/x86/fpu/enable_fpu.inc
|
||||
mainboardinit cpu/x86/mmx/emable_mmx.inc
|
||||
mainboardinit cpu/x86/sse/enable_sse.inc
|
||||
mainboardinit ./auto.inc
|
||||
mainboardinit cpu/p6/disable_mmx_sse.inc
|
||||
mainboardinit cpu/x86/sse/disable_sse.inc
|
||||
mainboardinit cpu/x86/mmx/disable_mmx.inc
|
||||
|
||||
##
|
||||
## Include the secondary Configuration files
|
||||
|
@ -212,61 +215,66 @@ mainboardinit cpu/p6/disable_mmx_sse.inc
|
|||
dir /pc80
|
||||
config chip.h
|
||||
|
||||
northbridge intel/i855pm "i855pm"
|
||||
# pci 0:0.0
|
||||
# pci 0:1.0
|
||||
southbridge intel/i82801dbm "i82801dbm"
|
||||
# pci 0:11.0
|
||||
# pci 0:11.1
|
||||
# pci 0:11.2
|
||||
# pci 0:11.3
|
||||
# pci 0:11.4
|
||||
# pci 0:11.5
|
||||
# pci 0:11.6
|
||||
# pci 0:12.0
|
||||
register "enable_usb" = "0"
|
||||
register "enable_native_ide" = "0"
|
||||
register "enable_usb" = "0"
|
||||
register "enable_native_ide" = "0"
|
||||
superio winbond/w83627hf link 1
|
||||
pnp 2e.0 on # Floppy
|
||||
io 0x60 = 0x3f0
|
||||
irq 0x70 = 6
|
||||
drq 0x74 = 2
|
||||
pnp 2e.1 off # Parallel Port
|
||||
io 0x60 = 0x378
|
||||
irq 0x70 = 7
|
||||
pnp 2e.2 on # Com1
|
||||
io 0x60 = 0x3f8
|
||||
irq 0x70 = 4
|
||||
pnp 2e.3 off # Com2
|
||||
io 0x60 = 0x2f8
|
||||
irq 0x70 = 3
|
||||
pnp 2e.5 on # Keyboard
|
||||
io 0x60 = 0x60
|
||||
io 0x62 = 0x64
|
||||
irq 0x70 = 1
|
||||
irq 0x72 = 12
|
||||
pnp 2e.6 off # CIR
|
||||
pnp 2e.7 off # GAME_MIDI_GIPO1
|
||||
pnp 2e.8 off # GPIO2
|
||||
pnp 2e.9 off # GPIO3
|
||||
pnp 2e.a off # ACPI
|
||||
pnp 2e.b on # HW Monitor
|
||||
io 0x60 = 0x290
|
||||
register "com1" = "{1}"
|
||||
# register "com1" = "{1, 0, 0x3f8, 4}"
|
||||
# register "lpt" = "{1}"
|
||||
end
|
||||
## This does not look right but it is a literal conversion of the
|
||||
## old version of this file.
|
||||
chip northbridge/intel/i855pm
|
||||
device pci_domain 0 on
|
||||
device pci 0.0 on end
|
||||
device pci 1.0 on end
|
||||
chip southbridge/intel/i82801dbm
|
||||
# pci 11.0 on end
|
||||
# pci 11.1 on end
|
||||
# pci 11.2 on end
|
||||
# pci 11.3 on end
|
||||
# pci 11.4 on end
|
||||
# pci 11.5 on end
|
||||
# pci 11.6 on end
|
||||
# pci 12.0 on end
|
||||
register "enable_usb" = "0"
|
||||
register "enable_native_ide" = "0"
|
||||
register "enable_usb" = "0"
|
||||
register "enable_native_ide" = "0"
|
||||
chip superio/winbond/w83627hf # link 1
|
||||
device pnp 2e.0 on # Floppy
|
||||
io 0x60 = 0x3f0
|
||||
irq 0x70 = 6
|
||||
drq 0x74 = 2
|
||||
end
|
||||
device pnp 2e.1 off # Parallel Port
|
||||
io 0x60 = 0x378
|
||||
irq 0x70 = 7
|
||||
end
|
||||
device pnp 2e.2 on # Com1
|
||||
io 0x60 = 0x3f8
|
||||
irq 0x70 = 4
|
||||
end
|
||||
device pnp 2e.3 off # Com2
|
||||
io 0x60 = 0x2f8
|
||||
irq 0x70 = 3
|
||||
end
|
||||
device pnp 2e.5 on # Keyboard
|
||||
io 0x60 = 0x60
|
||||
io 0x62 = 0x64
|
||||
irq 0x70 = 1
|
||||
irq 0x72 = 12
|
||||
end
|
||||
device pnp 2e.6 off end # CIR
|
||||
device pnp 2e.7 off end # GAME_MIDI_GIPO1
|
||||
device pnp 2e.8 off end # GPIO2
|
||||
device pnp 2e.9 off end # GPIO3
|
||||
device pnp 2e.a off end # ACPI
|
||||
device pnp 2e.b on # HW Monitor
|
||||
io 0x60 = 0x290
|
||||
end
|
||||
register "com1" = "{1}"
|
||||
# register "com1" = "{1, 0, 0x3f8, 4}"
|
||||
# register "lpt" = "{1}"
|
||||
end
|
||||
end
|
||||
end
|
||||
device apic_cluster 0 on
|
||||
device cpu/intel/socket_mPGA479M
|
||||
apic 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
cpu p6 "cpu0"
|
||||
|
||||
end
|
||||
|
||||
##
|
||||
## Include the old serial code for those few places that still need it.
|
||||
##
|
||||
mainboardinit pc80/serial.inc
|
||||
mainboardinit arch/i386/lib/console.inc
|
||||
|
|
|
@ -205,12 +205,7 @@ dir /pc80
|
|||
dir /drivers/emulation/qemu
|
||||
config chip.h
|
||||
|
||||
northbridge emulation/qemu-i386 "nb_qemu"
|
||||
|
||||
chip northbridge/emulation/qemu-i386
|
||||
pci_domain 0
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
## Include the old serial code for those few places that still need it.
|
||||
##
|
||||
mainboardinit pc80/serial.inc
|
||||
mainboardinit arch/i386/lib/console.inc
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include <console/console.h>
|
||||
#include <arch/io.h>
|
||||
#include <stdint.h>
|
||||
#include <mem.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ids.h>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include <console/console.h>
|
||||
#include <arch/io.h>
|
||||
#include <stdint.h>
|
||||
#include <mem.h>
|
||||
#include <part/sizeram.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/hypertransport.h>
|
||||
|
@ -17,57 +15,102 @@ void hard_reset(void)
|
|||
printk_err("Hard_RESET!!!\n");
|
||||
}
|
||||
|
||||
struct mem_range *sizeram(void)
|
||||
#define BRIDGE_IO_MASK (IORESOURCE_IO | IORESOURCE_MEM)
|
||||
|
||||
static void pci_domain_read_resources(device_t dev)
|
||||
{
|
||||
unsigned long mmio_basek;
|
||||
static struct mem_range mem[10];
|
||||
device_t dev;
|
||||
int i, idx;
|
||||
unsigned char rambits;
|
||||
struct resource *resource;
|
||||
unsigned reg;
|
||||
|
||||
/* Initialize the system wide io space constraints */
|
||||
resource = new_resource(dev, 0);
|
||||
resource->base = 0x400;
|
||||
resource->limit = 0xffffUL;
|
||||
resource->flags = IORESOURCE_IO;
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
IORESOURCE_IO, IORESOURCE_IO);
|
||||
|
||||
/* Initialize the system wide memory resources constraints */
|
||||
resource = new_resource(dev, 1);
|
||||
resource->limit = 0xffffffffULL;
|
||||
resource->flags = IORESOURCE_MEM;
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
IORESOURCE_MEM, IORESOURCE_MEM);
|
||||
}
|
||||
|
||||
static void pci_domain_set_resources(device_t dev)
|
||||
{
|
||||
struct resource *resource, *last;
|
||||
device_t mc_dev;
|
||||
uint32_t pci_tolm;
|
||||
|
||||
pci_tolm = 0xffffffffUL;
|
||||
last = &dev->resource[dev->resources];
|
||||
for(resource = &dev->resource[0]; resource < last; resource++)
|
||||
{
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
BRIDGE_IO_MASK, resource->flags & BRIDGE_IO_MASK);
|
||||
|
||||
resource->flags |= IORESOURCE_STORED;
|
||||
report_resource_stored(dev, resource, "");
|
||||
|
||||
if ((resource->flags & IORESOURCE_MEM) &&
|
||||
(pci_tolm > resource->base))
|
||||
{
|
||||
pci_tolm = resource->base;
|
||||
}
|
||||
}
|
||||
|
||||
dev = dev_find_slot(0, 0);
|
||||
if (!dev) {
|
||||
printk_err("Cannot find PCI: 0:0\n");
|
||||
return 0;
|
||||
}
|
||||
mem[0].basek = 0;
|
||||
mem[0].sizek = 65536;
|
||||
#if 0
|
||||
idx = 1;
|
||||
while(idx < sizeof(mem)/sizeof(mem[0])) {
|
||||
mem[idx].basek = 0;
|
||||
mem[idx].sizek = 0;
|
||||
idx++;
|
||||
}
|
||||
for(rambits = 0, i = 0; i < sizeof(ramregs)/sizeof(ramregs[0]); i++) {
|
||||
unsigned char reg;
|
||||
reg = pci_read_config8(dev, ramregs[i]);
|
||||
/* these are ENDING addresses, not sizes.
|
||||
* if there is memory in this slot, then reg will be > rambits.
|
||||
* So we just take the max, that gives us total.
|
||||
* We take the highest one to cover for once and future linuxbios
|
||||
* bugs. We warn about bugs.
|
||||
*/
|
||||
if (reg > rambits)
|
||||
rambits = reg;
|
||||
if (reg < rambits)
|
||||
printk_err("ERROR! register 0x%x is not set!\n",
|
||||
ramregs[i]);
|
||||
}
|
||||
|
||||
printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*8*1024);
|
||||
mem[0].sizek = rambits*8*1024;
|
||||
#endif
|
||||
#if 1
|
||||
for(i = 0; i < idx; i++) {
|
||||
printk_debug("mem[%d].basek = %08x mem[%d].sizek = %08x\n",
|
||||
i, mem[i].basek, i, mem[i].sizek);
|
||||
mc_dev = dev->link[0].children;
|
||||
if (mc_dev) {
|
||||
unsigned long tomk, tolmk;
|
||||
/* Hard code the Top of memory for now */
|
||||
tomk = 65536;
|
||||
/* Compute the top of Low memory */
|
||||
tolmk = pci_tolm >> 10;
|
||||
if (tolmk >= tomk) {
|
||||
/* The PCI hole does not overlap memory.
|
||||
*/
|
||||
tolmk = tomk;
|
||||
}
|
||||
|
||||
/* Report the memory regions */
|
||||
idx = 10;
|
||||
ram_resource(dev, idx++, 0, 640);
|
||||
ram_resource(dev, idx++, 768, tolmk - 768);
|
||||
if (tomk > 4*1024*1024) {
|
||||
ram_resource(dev, idx++, 4096*1024, tomk - 4*1024*1024);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
assign_resources(&dev->link[0]);
|
||||
}
|
||||
|
||||
return mem;
|
||||
static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
|
||||
{
|
||||
max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
|
||||
return max;
|
||||
}
|
||||
|
||||
static struct device_operations pci_domain_ops = {
|
||||
.read_resources = pci_domain_read_resources,
|
||||
.set_resources = pci_domain_set_resources,
|
||||
.enable_resources = enable_childrens_resources,
|
||||
.init = 0,
|
||||
.scan_bus = pci_domain_scan_bus,
|
||||
};
|
||||
|
||||
static void enable_dev(struct device *dev)
|
||||
{
|
||||
struct device_path path;
|
||||
|
||||
/* Set the operations if it is a special bus type */
|
||||
if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
|
||||
dev->ops = &pci_domain_ops;
|
||||
}
|
||||
}
|
||||
|
||||
struct chip_operations northbridge_emulation_qemu_i386_control = {
|
||||
.name = "QEMU Northbridge",
|
||||
.enable_dev = enable_dev,
|
||||
};
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include <console/console.h>
|
||||
#include <arch/io.h>
|
||||
#include <stdint.h>
|
||||
#include <mem.h>
|
||||
#include <part/sizeram.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -172,7 +170,7 @@ static struct device_operations cpu_bus_ops = {
|
|||
.set_resources = cpu_bus_noop,
|
||||
.enable_resources = cpu_bus_noop,
|
||||
.init = cpu_bus_init,
|
||||
.scan_bus = cpu_bus_noop,
|
||||
.scan_bus = 0,
|
||||
};
|
||||
|
||||
static void enable_dev(struct device *dev)
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include <console/console.h>
|
||||
#include <arch/io.h>
|
||||
#include <stdint.h>
|
||||
#include <mem.h>
|
||||
#include <part/sizeram.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -10,110 +8,152 @@
|
|||
#include <bitops.h>
|
||||
#include "chip.h"
|
||||
|
||||
struct mem_range *sizeram(void)
|
||||
#define BRIDGE_IO_MASK (IORESOURCE_IO | IORESOURCE_MEM)
|
||||
|
||||
static void pci_domain_read_resources(device_t dev)
|
||||
{
|
||||
static struct mem_range mem[4];
|
||||
/* the units of tolm are 64 KB */
|
||||
/* the units of drb16 are 64 MB */
|
||||
uint16_t tolm, remapbase, remaplimit, drb16;
|
||||
uint16_t tolm_r, remapbase_r, remaplimit_r;
|
||||
uint8_t drb;
|
||||
int remap_high;
|
||||
device_t dev;
|
||||
struct resource *resource;
|
||||
unsigned reg;
|
||||
|
||||
dev = dev_find_slot(0, 0); // d0f0
|
||||
if (!dev) {
|
||||
printk_err("Cannot find PCI: 0:0\n");
|
||||
return 0;
|
||||
/* Initialize the system wide io space constraints */
|
||||
resource = new_resource(dev, 0);
|
||||
resource->base = 0x400;
|
||||
resource->limit = 0xffffUL;
|
||||
resource->flags = IORESOURCE_IO;
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
IORESOURCE_IO, IORESOURCE_IO);
|
||||
|
||||
/* Initialize the system wide memory resources constraints */
|
||||
resource = new_resource(dev, 1);
|
||||
resource->limit = 0xffffffffULL;
|
||||
resource->flags = IORESOURCE_MEM;
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
IORESOURCE_MEM, IORESOURCE_MEM);
|
||||
}
|
||||
|
||||
static void ram_resource(device_t dev, unsigned long index,
|
||||
unsigned long basek, unsigned long sizek)
|
||||
{
|
||||
struct resource *resource;
|
||||
|
||||
if (!sizek) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Calculate and report the top of low memory and
|
||||
* any remapping.
|
||||
*/
|
||||
/* Test if the remap memory high option is set */
|
||||
remap_high = 0;
|
||||
// if(get_option(&remap_high, "remap_memory_high")){
|
||||
// remap_high = 0;
|
||||
// }
|
||||
printk_debug("remap_high is %d\n", remap_high);
|
||||
/* get out the value of the highest DRB. This tells the end of
|
||||
* physical memory. The units are ticks of 64 MB i.e. 1 means
|
||||
* 64 MB.
|
||||
*/
|
||||
drb = pci_read_config8(dev, 0x67);
|
||||
drb16 = (uint16_t)drb;
|
||||
if(remap_high && (drb16 > 0x08)) {
|
||||
/* We only come here if we have at least 512MB of memory,
|
||||
* so it is safe to hard code tolm.
|
||||
* 0x2000 means 512MB
|
||||
*/
|
||||
resource = new_resource(dev, index);
|
||||
resource->base = ((resource_t)basek) << 10;
|
||||
resource->size = ((resource_t)sizek) << 10;
|
||||
resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE | \
|
||||
IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
|
||||
}
|
||||
|
||||
tolm = 0x2000;
|
||||
/* i.e 0x40 * 0x40 is 0x1000 which is 4 GB */
|
||||
if(drb16 > 0x0040) {
|
||||
/* There is more than 4GB of memory put
|
||||
* the remap window at the end of ram.
|
||||
static void pci_domain_set_resources(device_t dev)
|
||||
{
|
||||
struct resource *resource, *last;
|
||||
device_t mc_dev;
|
||||
uint32_t pci_tolm;
|
||||
|
||||
pci_tolm = 0xffffffffUL;
|
||||
last = &dev->resource[dev->resources];
|
||||
for(resource = &dev->resource[0]; resource < last; resource++)
|
||||
{
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
BRIDGE_IO_MASK, resource->flags & BRIDGE_IO_MASK);
|
||||
|
||||
resource->flags |= IORESOURCE_STORED;
|
||||
report_resource_stored(dev, resource, "");
|
||||
|
||||
if ((resource->flags & IORESOURCE_MEM) &&
|
||||
(pci_tolm > resource->base))
|
||||
{
|
||||
pci_tolm = resource->base;
|
||||
}
|
||||
}
|
||||
|
||||
mc_dev = dev->link[0].children;
|
||||
if (mc_dev) {
|
||||
/* Figure out which areas are/should be occupied by RAM.
|
||||
* This is all computed in kilobytes and converted to/from
|
||||
* the memory controller right at the edges.
|
||||
* Having different variables in different units is
|
||||
* too confusing to get right. Kilobytes are good up to
|
||||
* 4 Terabytes of RAM...
|
||||
*/
|
||||
uint16_t tolm_r;
|
||||
unsigned long tomk, tolmk;
|
||||
int idx;
|
||||
|
||||
/* Get the value of the highest DRB. This tells the end of
|
||||
* the physical memory. The units are ticks of 32MB
|
||||
* i.e. 1 means 32MB.
|
||||
*/
|
||||
tomk = ((unsigned long)pci_read_config8(mc_dev, 0x63)) << 15;
|
||||
/* Compute the top of Low memory */
|
||||
tolmk = pci_tolm >> 10;
|
||||
if (tolmk >= tomk) {
|
||||
/* The PCI hole does does not overlap the memory.
|
||||
*/
|
||||
remapbase = drb16;
|
||||
remaplimit = remapbase + 0x38;
|
||||
tolmk = tomk;
|
||||
}
|
||||
else {
|
||||
remapbase = 0x0040;
|
||||
remaplimit = remapbase + (drb16-8);
|
||||
}
|
||||
}
|
||||
else {
|
||||
tolm = (uint16_t)((dev_root.resource[1].base >> 16)&0x0f800);
|
||||
if((tolm>>8) >= (drb16<<2)) {
|
||||
tolm = (drb16<<10);
|
||||
remapbase = 0x3ff;
|
||||
remaplimit = 0;
|
||||
}
|
||||
else {
|
||||
remapbase = drb16;
|
||||
remaplimit = remapbase + ((0x0040-(tolm>>10))-1);
|
||||
}
|
||||
}
|
||||
/* Write the ram configruation registers,
|
||||
* preserving the reserved bits.
|
||||
*/
|
||||
tolm_r = pci_read_config16(dev, 0xc4);
|
||||
tolm |= (tolm_r & 0x7ff);
|
||||
pci_write_config16(dev, 0xc4, tolm);
|
||||
remapbase_r = pci_read_config16(dev, 0xc6);
|
||||
remapbase |= (remapbase_r & 0xfc00);
|
||||
pci_write_config16(dev, 0xc6, remapbase);
|
||||
remaplimit_r = pci_read_config16(dev, 0xc8);
|
||||
remaplimit |= (remaplimit_r & 0xfc00);
|
||||
pci_write_config16(dev, 0xc8, remaplimit);
|
||||
|
||||
#if 0
|
||||
printk_debug("mem info tolm = %x, drb = %x, pci_memory_base = %x, remap = %x-%x\n",tolm,drb,pci_memory_base,remapbase,remaplimit);
|
||||
#endif
|
||||
|
||||
mem[0].basek = 0;
|
||||
mem[0].sizek = 640;
|
||||
mem[1].basek = 768;
|
||||
/* Convert size in 64K bytes to size in K bytes */
|
||||
mem[1].sizek = (tolm << 6) - mem[1].basek;
|
||||
mem[2].basek = 0;
|
||||
mem[2].sizek = 0;
|
||||
if ((drb << 16) > (tolm << 6)) {
|
||||
/* We don't need to consider the remap window
|
||||
* here because we put it immediately after the
|
||||
* rest of ram.
|
||||
* All we must do is calculate the amount
|
||||
* of unused memory and report it at 4GB.
|
||||
/* Write the ram configuration registers,
|
||||
* preserving the reserved bits.
|
||||
*/
|
||||
mem[2].basek = 4096*1024;
|
||||
mem[2].sizek = (drb << 16) - (tolm << 6);
|
||||
tolm_r = pci_read_config16(mc_dev, 0xc4);
|
||||
tolm_r = ((tolmk >> 10) << 3) | (tolm_r & 0xf);
|
||||
pci_write_config16(mc_dev, 0xc4, tolm_r);
|
||||
|
||||
/* Report the memory regions */
|
||||
idx = 10;
|
||||
ram_resource(dev, idx++, 0, 640);
|
||||
ram_resource(dev, idx++, 768, tolmk - 768);
|
||||
}
|
||||
mem[3].basek = 0;
|
||||
mem[3].sizek = 0;
|
||||
|
||||
return mem;
|
||||
assign_resources(&dev->link[0]);
|
||||
}
|
||||
|
||||
static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
|
||||
{
|
||||
max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
|
||||
return max;
|
||||
}
|
||||
|
||||
static struct device_operations pci_domain_ops = {
|
||||
.read_resources = pci_domain_read_resources,
|
||||
.set_resources = pci_domain_set_resources,
|
||||
.enable_resources = enable_childrens_resources,
|
||||
.init = 0,
|
||||
.scan_bus = pci_domain_scan_bus,
|
||||
};
|
||||
|
||||
static void cpu_bus_init(device_t dev)
|
||||
{
|
||||
initialize_cpus(&dev->link[0]);
|
||||
}
|
||||
|
||||
static void cpu_bus_noop(device_t dev)
|
||||
{
|
||||
}
|
||||
|
||||
static struct device_operations cpu_bus_ops = {
|
||||
.read_resources = cpu_bus_noop,
|
||||
.set_resources = cpu_bus_noop,
|
||||
.enable_resources = cpu_bus_noop,
|
||||
.init = cpu_bus_init,
|
||||
.scan_bus = 0,
|
||||
};
|
||||
|
||||
static void enable_dev(struct device *dev)
|
||||
{
|
||||
struct device_path path;
|
||||
|
||||
/* Set the operations if it is a special bus type */
|
||||
if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
|
||||
dev->ops = &pci_domain_ops;
|
||||
}
|
||||
else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
|
||||
dev->ops = &cpu_bus_ops;
|
||||
}
|
||||
}
|
||||
|
||||
struct chip_operations northbridge_intel_i855pm_control = {
|
||||
.name = "intel i855pm Northbridge",
|
||||
.name = "intel i855pm Northbridge",
|
||||
.enable_dev = enable_dev,
|
||||
};
|
||||
|
|
|
@ -314,272 +314,272 @@ mpc107_init(void)
|
|||
unsigned long
|
||||
mpc107_config_memory(int no_banks, sdram_bank_info * bank, int for_real)
|
||||
{
|
||||
int i, j;
|
||||
char ignore[8];
|
||||
/* Convert bus clock to cycle time in 100ns units */
|
||||
unsigned cycle_time = 10 * (2500000000U / get_timer_freq());
|
||||
/* Approximate */
|
||||
unsigned access_time = cycle_time - 300;
|
||||
unsigned cas_latency = 0;
|
||||
unsigned rdlat;
|
||||
unsigned refint;
|
||||
unsigned refrec;
|
||||
unsigned acttorw, acttopre;
|
||||
unsigned pretoact, bstopre;
|
||||
enum sdram_error_detect error_detect;
|
||||
uint32_t mccr1;
|
||||
uint32_t mccr2;
|
||||
uint32_t mccr3;
|
||||
uint32_t mccr4;
|
||||
uint8_t bank_enable;
|
||||
uint32_t memstart1, memstart2;
|
||||
uint32_t extmemstart1, extmemstart2;
|
||||
uint32_t memend1, memend2;
|
||||
uint32_t extmemend1, extmemend2;
|
||||
uint32_t address;
|
||||
int i, j;
|
||||
char ignore[8];
|
||||
/* Convert bus clock to cycle time in 100ns units */
|
||||
unsigned cycle_time = 10 * (2500000000U / get_timer_freq());
|
||||
/* Approximate */
|
||||
unsigned access_time = cycle_time - 300;
|
||||
unsigned cas_latency = 0;
|
||||
unsigned rdlat;
|
||||
unsigned refint;
|
||||
unsigned refrec;
|
||||
unsigned acttorw, acttopre;
|
||||
unsigned pretoact, bstopre;
|
||||
enum sdram_error_detect error_detect;
|
||||
uint32_t mccr1;
|
||||
uint32_t mccr2;
|
||||
uint32_t mccr3;
|
||||
uint32_t mccr4;
|
||||
uint8_t bank_enable;
|
||||
uint32_t memstart1, memstart2;
|
||||
uint32_t extmemstart1, extmemstart2;
|
||||
uint32_t memend1, memend2;
|
||||
uint32_t extmemend1, extmemend2;
|
||||
uint32_t address;
|
||||
|
||||
/* Set up the ignore mask */
|
||||
for(i = 0; i < no_banks; i++)
|
||||
ignore[i] = (bank[i].size == 0);
|
||||
/* Set up the ignore mask */
|
||||
for(i = 0; i < no_banks; i++)
|
||||
ignore[i] = (bank[i].size == 0);
|
||||
|
||||
/* Pick best CAS latency possible */
|
||||
for (i = 0; i < no_banks; i++)
|
||||
{
|
||||
if (! ignore[i])
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
if (cycle_time >= bank[i].cycle_time[j] &&
|
||||
access_time >= bank[i].access_time[j])
|
||||
{
|
||||
cas_latency = bank[i].cas_latency[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!cas_latency)
|
||||
return 0;
|
||||
|
||||
/* For various parameters there is a risk of clashing between banks */
|
||||
error_detect = (for_real > 1) ? ERRORS_ECC : ERRORS_NONE;
|
||||
for (i = 0; i < no_banks; i++)
|
||||
{
|
||||
if (! ignore[i])
|
||||
/* Pick best CAS latency possible */
|
||||
for (i = 0; i < no_banks; i++)
|
||||
{
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
if (bank[i].cas_latency[j] == cas_latency)
|
||||
break;
|
||||
if (j == 3)
|
||||
{
|
||||
ignore[i] = 1;
|
||||
if (! for_real)
|
||||
printk_info("Disabling memory bank %d (cas latency)\n", i);
|
||||
if (! ignore[i])
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
if (cycle_time >= bank[i].cycle_time[j] &&
|
||||
access_time >= bank[i].access_time[j])
|
||||
{
|
||||
cas_latency = bank[i].cas_latency[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bank[i].error_detect < error_detect)
|
||||
error_detect = bank[i].error_detect;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!cas_latency)
|
||||
return 0;
|
||||
|
||||
/* Read in configuration of port X */
|
||||
mccr1 = pci_ppc_read_config32(0, 0, 0xf0);
|
||||
mccr2 = pci_ppc_read_config32(0, 0, 0xf4);
|
||||
mccr4 = pci_ppc_read_config32(0, 0, 0xfc);
|
||||
mccr1 &= 0xfff00000;
|
||||
mccr2 &= 0xffe00000;
|
||||
mccr3 = 0;
|
||||
mccr4 &= 0x00230000;
|
||||
/* For various parameters there is a risk of clashing between banks */
|
||||
error_detect = (for_real > 1) ? ERRORS_ECC : ERRORS_NONE;
|
||||
for (i = 0; i < no_banks; i++)
|
||||
{
|
||||
if (! ignore[i])
|
||||
{
|
||||
{
|
||||
for (j = 0; j < 3; j++)
|
||||
if (bank[i].cas_latency[j] == cas_latency)
|
||||
break;
|
||||
if (j == 3)
|
||||
{
|
||||
ignore[i] = 1;
|
||||
if (! for_real)
|
||||
printk_info("Disabling memory bank %d (cas latency)\n", i);
|
||||
}
|
||||
if (bank[i].error_detect < error_detect)
|
||||
error_detect = bank[i].error_detect;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read in configuration of port X */
|
||||
mccr1 = pci_ppc_read_config32(0, 0, 0xf0);
|
||||
mccr2 = pci_ppc_read_config32(0, 0, 0xf4);
|
||||
mccr4 = pci_ppc_read_config32(0, 0, 0xfc);
|
||||
mccr1 &= 0xfff00000;
|
||||
mccr2 &= 0xffe00000;
|
||||
mccr3 = 0;
|
||||
mccr4 &= 0x00230000;
|
||||
|
||||
pretoact = 0;
|
||||
acttorw = 0;
|
||||
acttopre = 0;
|
||||
for (i = 0; i < no_banks; i++)
|
||||
if (! ignore[i])
|
||||
{
|
||||
int rowcode = -1;
|
||||
if (for_real)
|
||||
{
|
||||
bank[i].actual_detect = error_detect;
|
||||
bank[i].actual_cas = cas_latency;
|
||||
}
|
||||
|
||||
switch (bank[i].row_bits) {
|
||||
case 13:
|
||||
if (bank[i].internal_banks == 4)
|
||||
rowcode = 2;
|
||||
else if (bank[i].internal_banks == 2)
|
||||
rowcode = 1;
|
||||
break;
|
||||
case 12:
|
||||
if (bank[i].internal_banks == 4)
|
||||
rowcode = 0;
|
||||
else if (bank[i].internal_banks == 2)
|
||||
rowcode = 1;
|
||||
break;
|
||||
case 11:
|
||||
if (bank[i].internal_banks == 4)
|
||||
rowcode = 0;
|
||||
else if (bank[i].internal_banks == 2)
|
||||
rowcode = 3;
|
||||
break;
|
||||
}
|
||||
if (rowcode == -1) {
|
||||
ignore[i] = 1;
|
||||
if (! for_real)
|
||||
printk_info("Memory bank %d disabled: row bits %d and banks %d not supported\n", i, bank[i].row_bits, bank[i].internal_banks);
|
||||
} else
|
||||
mccr1 |= rowcode << (2 * i);
|
||||
|
||||
/* Update worst case settings */
|
||||
if (! ignore[i]) {
|
||||
if (bank[i].min_row_precharge > pretoact)
|
||||
pretoact = bank[i].min_row_precharge;
|
||||
if (bank[i].min_ras_to_cas > acttorw)
|
||||
acttorw = bank[i].min_ras_to_cas;
|
||||
if (bank[i].min_ras > acttopre)
|
||||
acttopre = bank[i].min_ras;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now convert to clock cycles, rounding up */
|
||||
pretoact = (100 * pretoact + cycle_time - 1) / cycle_time;
|
||||
acttopre = (100 * acttopre + cycle_time - 1) / cycle_time;
|
||||
acttorw = (100 * acttorw + cycle_time - 1) / cycle_time;
|
||||
refrec = acttopre;
|
||||
bstopre = 0x240; /* Set conservative values, because we can't derive */
|
||||
refint = 1000;
|
||||
|
||||
if (error_detect == ERRORS_ECC)
|
||||
{
|
||||
rdlat = cas_latency + 2;
|
||||
mccr4 |= 0x00400000;
|
||||
mccr2 |= 0x000c0001;
|
||||
}
|
||||
else
|
||||
{
|
||||
rdlat = cas_latency + 1;
|
||||
mccr4 |= 0x00100000;
|
||||
}
|
||||
|
||||
if (pretoact > 16 || acttopre > 16 || acttorw > 16)
|
||||
if (! for_real)
|
||||
printk_info("Timings out of range\n");
|
||||
mccr4 |= ((pretoact & 0x0f) << 28) | ((acttopre & 0xf) << 24) |
|
||||
((acttorw & 0x0f) << 4) |
|
||||
((bstopre & 0x003) << 18) | ((bstopre & 0x3c0) >> 6) |
|
||||
(cas_latency << 12) | 0x00000200 /* burst length */ ;
|
||||
mccr3 |= ((bstopre & 0x03c) << 26) |
|
||||
((refrec & 0x0f) << 24) | (rdlat << 20);
|
||||
mccr2 |= refint << 2;
|
||||
mccr1 |= 0x00080000; /* memgo */
|
||||
|
||||
address = 0;
|
||||
memstart1 = memstart2 = 0;
|
||||
extmemstart1 = extmemstart2 = 0;
|
||||
memend1 = memend2 = 0;
|
||||
extmemend1 = extmemend2 = 0;
|
||||
bank_enable = 0;
|
||||
for (i = 0; i < no_banks; i++) {
|
||||
if (! ignore[i]) {
|
||||
uint32_t end = address + bank[i].size - 1;
|
||||
bank_enable |= 1 << i;
|
||||
if (i < 4) {
|
||||
memstart1 |= ((address >> 20) & 0xff) << (8 * i);
|
||||
extmemstart1 |= ((address >> 28) & 0x03) << (8 * i);
|
||||
memend1 |= ((end >> 20) & 0xff) << (8 * i);
|
||||
extmemend1 |= ((end >> 28) & 0x03) << (8 * i);
|
||||
} else {
|
||||
int k = i - 4;
|
||||
memstart2 |= ((address >> 20) & 0xff) << (8 * k);
|
||||
extmemstart2 |= ((address >> 28) & 0x03) << (8 * k);
|
||||
memend2 |= ((end >> 20) & 0xff) << (8 * k);
|
||||
extmemend2 |= ((end >> 28) & 0x03) << (8 * k);
|
||||
}
|
||||
address += bank[i].size;
|
||||
}
|
||||
}
|
||||
|
||||
pretoact = 0;
|
||||
acttorw = 0;
|
||||
acttopre = 0;
|
||||
for (i = 0; i < no_banks; i++)
|
||||
if (! ignore[i])
|
||||
{
|
||||
int rowcode = -1;
|
||||
if (for_real)
|
||||
{
|
||||
bank[i].actual_detect = error_detect;
|
||||
bank[i].actual_cas = cas_latency;
|
||||
}
|
||||
|
||||
switch (bank[i].row_bits) {
|
||||
case 13:
|
||||
if (bank[i].internal_banks == 4)
|
||||
rowcode = 2;
|
||||
else if (bank[i].internal_banks == 2)
|
||||
rowcode = 1;
|
||||
break;
|
||||
case 12:
|
||||
if (bank[i].internal_banks == 4)
|
||||
rowcode = 0;
|
||||
else if (bank[i].internal_banks == 2)
|
||||
rowcode = 1;
|
||||
break;
|
||||
case 11:
|
||||
if (bank[i].internal_banks == 4)
|
||||
rowcode = 0;
|
||||
else if (bank[i].internal_banks == 2)
|
||||
rowcode = 3;
|
||||
break;
|
||||
}
|
||||
if (rowcode == -1) {
|
||||
ignore[i] = 1;
|
||||
if (! for_real)
|
||||
printk_info("Memory bank %d disabled: row bits %d and banks %d not supported\n", i, bank[i].row_bits, bank[i].internal_banks);
|
||||
} else
|
||||
mccr1 |= rowcode << (2 * i);
|
||||
/*
|
||||
* Mask MEMGO bit before setting MCCR1
|
||||
*/
|
||||
mccr1 &= ~0x80000;
|
||||
printk_info("MCCR1 = 0x%08x\n", mccr1);
|
||||
pci_ppc_write_config32(0, 0, 0xf0, mccr1);
|
||||
|
||||
/* Update worst case settings */
|
||||
if (! ignore[i]) {
|
||||
if (bank[i].min_row_precharge > pretoact)
|
||||
pretoact = bank[i].min_row_precharge;
|
||||
if (bank[i].min_ras_to_cas > acttorw)
|
||||
acttorw = bank[i].min_ras_to_cas;
|
||||
if (bank[i].min_ras > acttopre)
|
||||
acttopre = bank[i].min_ras;
|
||||
printk_info("MBEN = 0x%02x\n", bank_enable);
|
||||
pci_ppc_write_config8(0, 0, 0xa0, bank_enable);
|
||||
printk_info("MSAR1 = 0x%08x\n", memstart1);
|
||||
pci_ppc_write_config32(0, 0, 0x80, memstart1);
|
||||
printk_info("MSAR2 = 0x%08x\n", memstart2);
|
||||
pci_ppc_write_config32(0, 0, 0x84, memstart2);
|
||||
printk_info("MSAR3 = 0x%08x\n", extmemstart1);
|
||||
pci_ppc_write_config32(0, 0, 0x88, extmemstart1);
|
||||
printk_info("MSAR4 = 0x%08x\n", extmemstart2);
|
||||
pci_ppc_write_config32(0, 0, 0x8c, extmemstart2);
|
||||
printk_info("MEAR1 = 0x%08x\n", memend1);
|
||||
pci_ppc_write_config32(0, 0, 0x90, memend1);
|
||||
printk_info("MEAR2 = 0x%08x\n", memend2);
|
||||
pci_ppc_write_config32(0, 0, 0x94, memend2);
|
||||
printk_info("MEAR3 = 0x%08x\n", extmemend1);
|
||||
pci_ppc_write_config32(0, 0, 0x98, extmemend1);
|
||||
printk_info("MEAR4 = 0x%08x\n", extmemend2);
|
||||
pci_ppc_write_config32(0, 0, 0x9c, extmemend2);
|
||||
printk_info("MCCR2 = 0x%08x\n", mccr2);
|
||||
pci_ppc_write_config32(0, 0, 0xf4, mccr2);
|
||||
printk_info("MCCR3 = 0x%08x\n", mccr3);
|
||||
pci_ppc_write_config32(0, 0, 0xf8, mccr3);
|
||||
printk_info("MCCR4 = 0x%08x\n", mccr4);
|
||||
pci_ppc_write_config32(0, 0, 0xfc, mccr4);
|
||||
|
||||
udelay(200);
|
||||
|
||||
/*
|
||||
* Set MEMGO bit
|
||||
*/
|
||||
mccr1 |= 0x80000;
|
||||
printk_info("MCCR1 = 0x%08x\n", mccr1);
|
||||
pci_ppc_write_config32(0, 0, 0xf0, mccr1);
|
||||
|
||||
udelay(10000);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now convert to clock cycles, rounding up */
|
||||
pretoact = (100 * pretoact + cycle_time - 1) / cycle_time;
|
||||
acttopre = (100 * acttopre + cycle_time - 1) / cycle_time;
|
||||
acttorw = (100 * acttorw + cycle_time - 1) / cycle_time;
|
||||
refrec = acttopre;
|
||||
bstopre = 0x240; /* Set conservative values, because we can't derive */
|
||||
refint = 1000;
|
||||
|
||||
if (error_detect == ERRORS_ECC)
|
||||
{
|
||||
rdlat = cas_latency + 2;
|
||||
mccr4 |= 0x00400000;
|
||||
mccr2 |= 0x000c0001;
|
||||
}
|
||||
else
|
||||
{
|
||||
rdlat = cas_latency + 1;
|
||||
mccr4 |= 0x00100000;
|
||||
}
|
||||
|
||||
if (pretoact > 16 || acttopre > 16 || acttorw > 16)
|
||||
if (! for_real)
|
||||
printk_info("Timings out of range\n");
|
||||
mccr4 |= ((pretoact & 0x0f) << 28) | ((acttopre & 0xf) << 24) |
|
||||
((acttorw & 0x0f) << 4) |
|
||||
((bstopre & 0x003) << 18) | ((bstopre & 0x3c0) >> 6) |
|
||||
(cas_latency << 12) | 0x00000200 /* burst length */ ;
|
||||
mccr3 |= ((bstopre & 0x03c) << 26) |
|
||||
((refrec & 0x0f) << 24) | (rdlat << 20);
|
||||
mccr2 |= refint << 2;
|
||||
mccr1 |= 0x00080000; /* memgo */
|
||||
|
||||
address = 0;
|
||||
memstart1 = memstart2 = 0;
|
||||
extmemstart1 = extmemstart2 = 0;
|
||||
memend1 = memend2 = 0;
|
||||
extmemend1 = extmemend2 = 0;
|
||||
bank_enable = 0;
|
||||
for (i = 0; i < no_banks; i++) {
|
||||
if (! ignore[i]) {
|
||||
uint32_t end = address + bank[i].size - 1;
|
||||
bank_enable |= 1 << i;
|
||||
if (i < 4) {
|
||||
memstart1 |= ((address >> 20) & 0xff) << (8 * i);
|
||||
extmemstart1 |= ((address >> 28) & 0x03) << (8 * i);
|
||||
memend1 |= ((end >> 20) & 0xff) << (8 * i);
|
||||
extmemend1 |= ((end >> 28) & 0x03) << (8 * i);
|
||||
} else {
|
||||
int k = i - 4;
|
||||
memstart2 |= ((address >> 20) & 0xff) << (8 * k);
|
||||
extmemstart2 |= ((address >> 28) & 0x03) << (8 * k);
|
||||
memend2 |= ((end >> 20) & 0xff) << (8 * k);
|
||||
extmemend2 |= ((end >> 28) & 0x03) << (8 * k);
|
||||
}
|
||||
address += bank[i].size;
|
||||
}
|
||||
}
|
||||
|
||||
if (for_real)
|
||||
{
|
||||
/*
|
||||
* Mask MEMGO bit before setting MCCR1
|
||||
*/
|
||||
mccr1 &= ~0x80000;
|
||||
printk_info("MCCR1 = 0x%08x\n", mccr1);
|
||||
pci_ppc_write_config32(0, 0, 0xf0, mccr1);
|
||||
|
||||
printk_info("MBEN = 0x%02x\n", bank_enable);
|
||||
pci_ppc_write_config8(0, 0, 0xa0, bank_enable);
|
||||
printk_info("MSAR1 = 0x%08x\n", memstart1);
|
||||
pci_ppc_write_config32(0, 0, 0x80, memstart1);
|
||||
printk_info("MSAR2 = 0x%08x\n", memstart2);
|
||||
pci_ppc_write_config32(0, 0, 0x84, memstart2);
|
||||
printk_info("MSAR3 = 0x%08x\n", extmemstart1);
|
||||
pci_ppc_write_config32(0, 0, 0x88, extmemstart1);
|
||||
printk_info("MSAR4 = 0x%08x\n", extmemstart2);
|
||||
pci_ppc_write_config32(0, 0, 0x8c, extmemstart2);
|
||||
printk_info("MEAR1 = 0x%08x\n", memend1);
|
||||
pci_ppc_write_config32(0, 0, 0x90, memend1);
|
||||
printk_info("MEAR2 = 0x%08x\n", memend2);
|
||||
pci_ppc_write_config32(0, 0, 0x94, memend2);
|
||||
printk_info("MEAR3 = 0x%08x\n", extmemend1);
|
||||
pci_ppc_write_config32(0, 0, 0x98, extmemend1);
|
||||
printk_info("MEAR4 = 0x%08x\n", extmemend2);
|
||||
pci_ppc_write_config32(0, 0, 0x9c, extmemend2);
|
||||
printk_info("MCCR2 = 0x%08x\n", mccr2);
|
||||
pci_ppc_write_config32(0, 0, 0xf4, mccr2);
|
||||
printk_info("MCCR3 = 0x%08x\n", mccr3);
|
||||
pci_ppc_write_config32(0, 0, 0xf8, mccr3);
|
||||
printk_info("MCCR4 = 0x%08x\n", mccr4);
|
||||
pci_ppc_write_config32(0, 0, 0xfc, mccr4);
|
||||
|
||||
udelay(200);
|
||||
|
||||
/*
|
||||
* Set MEMGO bit
|
||||
*/
|
||||
mccr1 |= 0x80000;
|
||||
printk_info("MCCR1 = 0x%08x\n", mccr1);
|
||||
pci_ppc_write_config32(0, 0, 0xf0, mccr1);
|
||||
|
||||
udelay(10000);
|
||||
}
|
||||
|
||||
return address;
|
||||
return address;
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_wait(unsigned timeout, int writing)
|
||||
{
|
||||
uint32_t x;
|
||||
while (((x = readl(MPC107_BASE + MPC107_I2CSR)) & (MPC107_I2C_CSR_MCF | MPC107_I2C_CSR_MIF))
|
||||
!= (MPC107_I2C_CSR_MCF | MPC107_I2C_CSR_MIF)) {
|
||||
if (ticks_since_boot() > timeout)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (x & MPC107_I2C_CSR_MAL) {
|
||||
return -1;
|
||||
}
|
||||
if (writing && (x & MPC107_I2C_CSR_RXAK)) {
|
||||
printk_info("No RXAK\n");
|
||||
/* generate stop */
|
||||
writel(MPC107_I2C_CCR_MEN, MPC107_BASE + MPC107_I2CCR);
|
||||
return -1;
|
||||
}
|
||||
writel(0, MPC107_BASE + MPC107_I2CSR);
|
||||
return 0;
|
||||
uint32_t x;
|
||||
while (((x = readl(MPC107_BASE + MPC107_I2CSR)) & (MPC107_I2C_CSR_MCF | MPC107_I2C_CSR_MIF))
|
||||
!= (MPC107_I2C_CSR_MCF | MPC107_I2C_CSR_MIF)) {
|
||||
if (ticks_since_boot() > timeout)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (x & MPC107_I2C_CSR_MAL) {
|
||||
return -1;
|
||||
}
|
||||
if (writing && (x & MPC107_I2C_CSR_RXAK)) {
|
||||
printk_info("No RXAK\n");
|
||||
/* generate stop */
|
||||
writel(MPC107_I2C_CCR_MEN, MPC107_BASE + MPC107_I2CCR);
|
||||
return -1;
|
||||
}
|
||||
writel(0, MPC107_BASE + MPC107_I2CSR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
mpc107_i2c_start(struct i2c_bus *bus)
|
||||
{
|
||||
/* Set clock */
|
||||
writel(0x1031, MPC107_BASE + MPC107_I2CFDR);
|
||||
/* Clear arbitration */
|
||||
writel(0, MPC107_BASE + MPC107_I2CSR);
|
||||
/* Set clock */
|
||||
writel(0x1031, MPC107_BASE + MPC107_I2CFDR);
|
||||
/* Clear arbitration */
|
||||
writel(0, MPC107_BASE + MPC107_I2CSR);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -680,27 +680,27 @@ mpc107_i2c_master_read(struct i2c_bus *bus, int target, int address,
|
|||
count = 0;
|
||||
while (count < length) {
|
||||
|
||||
if (i2c_wait(timeout, 0) < 0)
|
||||
return -1;
|
||||
|
||||
/* Generate txack on next to last byte */
|
||||
if (count == length - 2)
|
||||
writel(MPC107_I2C_CCR_MEN | MPC107_I2C_CCR_MSTA | MPC107_I2C_CCR_TXAK, MPC107_BASE + MPC107_I2CCR);
|
||||
/* Generate stop on last byte */
|
||||
if (count == length - 1)
|
||||
writel(MPC107_I2C_CCR_MEN | MPC107_I2C_CCR_TXAK, MPC107_BASE + MPC107_I2CCR);
|
||||
data[count] = readl(MPC107_BASE + MPC107_I2CDR);
|
||||
if (count == 0 && length == DIMM_LENGTH) {
|
||||
if (data[0] == 0xff) {
|
||||
printk_debug("I2C device not present\n");
|
||||
length = 3;
|
||||
} else {
|
||||
length = data[0];
|
||||
if (length < 3)
|
||||
length = 3;
|
||||
if (i2c_wait(timeout, 0) < 0)
|
||||
return -1;
|
||||
|
||||
/* Generate txack on next to last byte */
|
||||
if (count == length - 2)
|
||||
writel(MPC107_I2C_CCR_MEN | MPC107_I2C_CCR_MSTA | MPC107_I2C_CCR_TXAK, MPC107_BASE + MPC107_I2CCR);
|
||||
/* Generate stop on last byte */
|
||||
if (count == length - 1)
|
||||
writel(MPC107_I2C_CCR_MEN | MPC107_I2C_CCR_TXAK, MPC107_BASE + MPC107_I2CCR);
|
||||
data[count] = readl(MPC107_BASE + MPC107_I2CDR);
|
||||
if (count == 0 && length == DIMM_LENGTH) {
|
||||
if (data[0] == 0xff) {
|
||||
printk_debug("I2C device not present\n");
|
||||
length = 3;
|
||||
} else {
|
||||
length = data[0];
|
||||
if (length < 3)
|
||||
length = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
count++;
|
||||
count++;
|
||||
}
|
||||
|
||||
/* Finish with disable master */
|
||||
|
@ -709,8 +709,8 @@ mpc107_i2c_master_read(struct i2c_bus *bus, int target, int address,
|
|||
}
|
||||
|
||||
i2c_fn mpc107_i2c_fn = {
|
||||
mpc107_i2c_start, mpc107_i2c_stop,
|
||||
mpc107_i2c_master_write, mpc107_i2c_master_read
|
||||
mpc107_i2c_start, mpc107_i2c_stop,
|
||||
mpc107_i2c_master_write, mpc107_i2c_master_read
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -719,36 +719,36 @@ i2c_fn mpc107_i2c_fn = {
|
|||
void
|
||||
mpc107_probe_dimms(int no_dimms, sdram_dimm_info *dimms, sdram_bank_info * bank)
|
||||
{
|
||||
unsigned char data[256];
|
||||
unsigned dimm;
|
||||
|
||||
printk_debug("Probing DIMMS...\n");
|
||||
|
||||
mpc107_i2c_start(NULL);
|
||||
|
||||
for(dimm = 0; dimm < no_dimms; dimm++)
|
||||
{
|
||||
dimms[dimm].number = dimm;
|
||||
dimms[dimm].bank1 = bank + dimm*NUM_BANKS;
|
||||
dimms[dimm].bank2 = bank + dimm*NUM_BANKS + 1;
|
||||
bank[dimm*NUM_BANKS].size = 0;
|
||||
bank[dimm*NUM_BANKS+1].size = 0;
|
||||
bank[dimm*NUM_BANKS].number = 0;
|
||||
bank[dimm*NUM_BANKS+1].number = 1;
|
||||
}
|
||||
|
||||
|
||||
for (dimm = 0; dimm < no_dimms; dimm ++) {
|
||||
unsigned limit = mpc107_i2c_master_read(NULL, 0xa0 + 2*dimm, 0,
|
||||
data, DIMM_LENGTH);
|
||||
|
||||
if (limit > 3) {
|
||||
sdram_dimm_to_bank_info(data, dimms + dimm, 1);
|
||||
memcpy(dimms[dimm].part_number, data + 73, 18);
|
||||
dimms[dimm].part_number[18] = 0;
|
||||
printk_debug("Part Number: %s\n", dimms[dimm].part_number);
|
||||
unsigned char data[256];
|
||||
unsigned dimm;
|
||||
|
||||
printk_debug("Probing DIMMS...\n");
|
||||
|
||||
mpc107_i2c_start(NULL);
|
||||
|
||||
for(dimm = 0; dimm < no_dimms; dimm++)
|
||||
{
|
||||
dimms[dimm].number = dimm;
|
||||
dimms[dimm].bank1 = bank + dimm*NUM_BANKS;
|
||||
dimms[dimm].bank2 = bank + dimm*NUM_BANKS + 1;
|
||||
bank[dimm*NUM_BANKS].size = 0;
|
||||
bank[dimm*NUM_BANKS+1].size = 0;
|
||||
bank[dimm*NUM_BANKS].number = 0;
|
||||
bank[dimm*NUM_BANKS+1].number = 1;
|
||||
}
|
||||
}
|
||||
|
||||
mpc107_i2c_stop(NULL);
|
||||
|
||||
|
||||
for (dimm = 0; dimm < no_dimms; dimm ++) {
|
||||
unsigned limit = mpc107_i2c_master_read(NULL, 0xa0 + 2*dimm, 0,
|
||||
data, DIMM_LENGTH);
|
||||
|
||||
if (limit > 3) {
|
||||
sdram_dimm_to_bank_info(data, dimms + dimm, 1);
|
||||
memcpy(dimms[dimm].part_number, data + 73, 18);
|
||||
dimms[dimm].part_number[18] = 0;
|
||||
printk_debug("Part Number: %s\n", dimms[dimm].part_number);
|
||||
}
|
||||
}
|
||||
|
||||
mpc107_i2c_stop(NULL);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include <console/console.h>
|
||||
#include <arch/io.h>
|
||||
#include <stdint.h>
|
||||
#include <mem.h>
|
||||
#include <part/sizeram.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ids.h>
|
||||
|
@ -13,111 +11,141 @@
|
|||
#include "chip.h"
|
||||
#include "northbridge.h"
|
||||
|
||||
struct mem_range *sizeram(void)
|
||||
#define BRIDGE_IO_MASK (IORESOURCE_IO | IORESOURCE_MEM)
|
||||
|
||||
static void pci_domain_read_resources(device_t dev)
|
||||
{
|
||||
unsigned long mmio_basek;
|
||||
static struct mem_range mem[10];
|
||||
device_t dev;
|
||||
int i, idx;
|
||||
struct resource *resource;
|
||||
unsigned reg;
|
||||
|
||||
#warning "FIXME handle interleaved nodes"
|
||||
dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
|
||||
if (!dev) {
|
||||
printk_err("Cannot find PCI: 0:18.1\n");
|
||||
return 0;
|
||||
}
|
||||
mmio_basek = (dev_root.resource[1].base >> 10);
|
||||
/* Round mmio_basek to something the processor can support */
|
||||
mmio_basek &= ~((1 << 6) -1);
|
||||
/* Initialize the system wide io space constraints */
|
||||
resource = new_resource(dev, 0);
|
||||
resource->base = 0x400;
|
||||
resource->limit = 0xffffUL;
|
||||
resource->flags = IORESOURCE_IO;
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
IORESOURCE_IO, IORESOURCE_IO);
|
||||
|
||||
#if 1
|
||||
#warning "FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M MMIO hole"
|
||||
/* Round the mmio hold to 256M */
|
||||
mmio_basek &= ~((256*1024) - 1);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
printk_debug("mmio_base: %dKB\n", mmio_basek);
|
||||
#endif
|
||||
|
||||
for (idx = i = 0; i < 8; i++) {
|
||||
uint32_t base, limit;
|
||||
unsigned basek, limitk, sizek;
|
||||
base = pci_read_config32(dev, 0x40 + (i<<3));
|
||||
limit = pci_read_config32(dev, 0x44 + (i<<3));
|
||||
if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
|
||||
continue;
|
||||
}
|
||||
basek = (base & 0xffff0000) >> 2;
|
||||
limitk = ((limit + 0x00010000) & 0xffff0000) >> 2;
|
||||
sizek = limitk - basek;
|
||||
if ((idx > 0) &&
|
||||
((mem[idx - 1].basek + mem[idx - 1].sizek) == basek)) {
|
||||
mem[idx -1].sizek += sizek;
|
||||
} else {
|
||||
mem[idx].basek = basek;
|
||||
mem[idx].sizek = sizek;
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* see if we need a hole from 0xa0000 to 0xbffff */
|
||||
if ((mem[idx-1].basek < ((8*64)+(8*16))) /* 640 */ &&
|
||||
(mem[idx-1].sizek > ((8*64)+(16*16))) /* 768 */ ) {
|
||||
#warning "FIXME: this left 0xA0000 to 0xBFFFF undefined"
|
||||
mem[idx].basek = (8*64)+(16*16);
|
||||
mem[idx].sizek = mem[idx-1].sizek - ((8*64)+(16*16));
|
||||
mem[idx-1].sizek = ((8*64)+(8*16)) - mem[idx-1].basek;
|
||||
idx++;
|
||||
}
|
||||
|
||||
/* See if I need to split the region to accomodate pci memory space */
|
||||
if ((mem[idx - 1].basek <= mmio_basek) &&
|
||||
((mem[idx - 1].basek + mem[idx - 1].sizek) > mmio_basek)) {
|
||||
if (mem[idx - 1].basek < mmio_basek) {
|
||||
unsigned pre_sizek;
|
||||
pre_sizek = mmio_basek - mem[idx - 1].basek;
|
||||
mem[idx].basek = mmio_basek;
|
||||
mem[idx].sizek = mem[idx - 1].sizek - pre_sizek;
|
||||
mem[idx - 1].sizek = pre_sizek;
|
||||
idx++;
|
||||
}
|
||||
if ((mem[idx - 1].basek + mem[idx - 1].sizek) <= 4*1024*1024) {
|
||||
idx -= 1;
|
||||
} else {
|
||||
mem[idx - 1].basek = 4*1024*1024;
|
||||
mem[idx - 1].sizek -= (4*1024*1024 - mmio_basek);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 1
|
||||
for (i = 0; i < idx; i++) {
|
||||
printk_debug("mem[%d].basek = %08x mem[%d].sizek = %08x\n",
|
||||
i, mem[i].basek, i, mem[i].sizek);
|
||||
}
|
||||
#endif
|
||||
while (idx < sizeof(mem)/sizeof(mem[0])) {
|
||||
mem[idx].basek = 0;
|
||||
mem[idx].sizek = 0;
|
||||
idx++;
|
||||
}
|
||||
return mem;
|
||||
/* Initialize the system wide memory resources constraints */
|
||||
resource = new_resource(dev, 1);
|
||||
resource->limit = 0xffffffffULL;
|
||||
resource->flags = IORESOURCE_MEM;
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
IORESOURCE_MEM, IORESOURCE_MEM);
|
||||
}
|
||||
|
||||
static struct device_operations northbridge_operations = {
|
||||
.read_resources = tm5800_read_resources,
|
||||
.set_resources = tm5800_set_resources,
|
||||
.enable_resources = tm5800_enable_resources,
|
||||
.init = mcf0_control_init,
|
||||
.scan_bus = tm5800_scan_chains,
|
||||
.enable = 0,
|
||||
static void ram_resource(device_t dev, unsigned long index,
|
||||
unsigned long basek, unsigned long sizek)
|
||||
{
|
||||
struct resource *resource;
|
||||
|
||||
if (!sizek) {
|
||||
return;
|
||||
}
|
||||
resource = new_resource(dev, index);
|
||||
resource->base = ((resource_t)basek) << 10;
|
||||
resource->size = ((resource_t)sizek) << 10;
|
||||
resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE | \
|
||||
IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
|
||||
}
|
||||
|
||||
static void pci_domain_set_resources(device_t dev)
|
||||
{
|
||||
struct resource *resource, *last;
|
||||
device_t mc_dev;
|
||||
uint32_t pci_tolm;
|
||||
|
||||
pci_tolm = 0xffffffffUL;
|
||||
last = &dev->resource[dev->resources];
|
||||
for(resource = &dev->resource[0]; resource < last; resource++)
|
||||
{
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
BRIDGE_IO_MASK, resource->flags & BRIDGE_IO_MASK);
|
||||
|
||||
resource->flags |= IORESOURCE_STORED;
|
||||
report_resource_stored(dev, resource, "");
|
||||
|
||||
if ((resource->flags & IORESOURCE_MEM) &&
|
||||
(pci_tolm > resource->base))
|
||||
{
|
||||
pci_tolm = resource->base;
|
||||
}
|
||||
}
|
||||
|
||||
mc_dev = dev->link[0].children;
|
||||
if (mc_dev) {
|
||||
/* Figure out which areas are/should be occupied by RAM.
|
||||
* This is all computed in kilobytes and converted to/from
|
||||
* the memory controller right at the edges.
|
||||
* Having different variables in different units is
|
||||
* too confusing to get right. Kilobytes are good up to
|
||||
* 4 Terabytes of RAM...
|
||||
*/
|
||||
unsigned long tomk, tolmk;
|
||||
int idx;
|
||||
|
||||
#warning "This is hardcoded to 1MiB of RAM for now"
|
||||
tomk = 1024;
|
||||
/* Compute the top of Low memory */
|
||||
tolmk = pci_tolm >> 10;
|
||||
if (tolmk >= tomk) {
|
||||
/* The PCI hole does does not overlap the memory.
|
||||
*/
|
||||
tolmk = tomk;
|
||||
}
|
||||
/* Report the memory regions */
|
||||
idx = 10;
|
||||
ram_resource(dev, idx++, 0, 640);
|
||||
ram_resource(dev, idx++, 768, tolmk - 768);
|
||||
}
|
||||
assign_resources(&dev->link[0]);
|
||||
}
|
||||
|
||||
static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
|
||||
{
|
||||
max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
|
||||
return max;
|
||||
}
|
||||
|
||||
static struct device_operations pci_domain_ops = {
|
||||
.read_resources = pci_domain_read_resources,
|
||||
.set_resources = pci_domain_set_resources,
|
||||
.enable_resources = enable_childrens_resources,
|
||||
.init = 0,
|
||||
.scan_bus = pci_domain_scan_bus,
|
||||
};
|
||||
|
||||
static void cpu_bus_init(device_t dev)
|
||||
{
|
||||
initialize_cpus(&dev->link[0]);
|
||||
}
|
||||
|
||||
static void cpu_bus_noop(device_t dev)
|
||||
{
|
||||
}
|
||||
|
||||
static struct device_operations cpu_bus_ops = {
|
||||
.read_resources = cpu_bus_noop,
|
||||
.set_resources = cpu_bus_noop,
|
||||
.enable_resources = cpu_bus_noop,
|
||||
.init = cpu_bus_init,
|
||||
.scan_bus = 0,
|
||||
};
|
||||
|
||||
static struct pci_driver mcf0_driver __pci_driver = {
|
||||
.ops = &northbridge_operations,
|
||||
.vendor = PCI_VENDOR_ID_AMD,
|
||||
.device = 0x1100,
|
||||
};
|
||||
static void enable_dev(struct device *dev)
|
||||
{
|
||||
struct device_path path;
|
||||
|
||||
struct chip_operations northbridge_amd_tm5800_control = {
|
||||
.name = "Transmeta tm5800 Northbridge",
|
||||
/* Set the operations if it is a special bus type */
|
||||
if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
|
||||
dev->ops = &pci_domain_ops;
|
||||
}
|
||||
else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
|
||||
dev->ops = &cpu_bus_ops;
|
||||
}
|
||||
}
|
||||
|
||||
struct chip_operations northbridge_transmeta_tm5800_control = {
|
||||
.name = "Transmeta tm5800 Northbridge",
|
||||
.enable_dev = enable_dev,
|
||||
};
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include <console/console.h>
|
||||
#include <arch/io.h>
|
||||
#include <stdint.h>
|
||||
#include <mem.h>
|
||||
#include <part/sizeram.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/hypertransport.h>
|
||||
|
@ -12,103 +10,189 @@
|
|||
#include "chip.h"
|
||||
#include "northbridge.h"
|
||||
|
||||
static const uint8_t ramregs[] = {0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x56, 0x57};
|
||||
|
||||
struct mem_range *sizeram(void)
|
||||
{
|
||||
unsigned long mmio_basek;
|
||||
static struct mem_range mem[10];
|
||||
device_t dev;
|
||||
int i, idx;
|
||||
unsigned char rambits;
|
||||
|
||||
dev = dev_find_slot(0, 0);
|
||||
if (!dev) {
|
||||
printk_err("Cannot find PCI: 0:0\n");
|
||||
return 0;
|
||||
}
|
||||
mem[0].basek = 0;
|
||||
mem[0].sizek = 65536;
|
||||
idx = 1;
|
||||
while(idx < sizeof(mem)/sizeof(mem[0])) {
|
||||
mem[idx].basek = 0;
|
||||
mem[idx].sizek = 0;
|
||||
idx++;
|
||||
}
|
||||
for(rambits = 0, i = 0; i < sizeof(ramregs)/sizeof(ramregs[0]); i++) {
|
||||
unsigned char reg;
|
||||
reg = pci_read_config8(dev, ramregs[i]);
|
||||
/* these are ENDING addresses, not sizes.
|
||||
* if there is memory in this slot, then reg will be > rambits.
|
||||
* So we just take the max, that gives us total.
|
||||
* We take the highest one to cover for once and future linuxbios
|
||||
* bugs. We warn about bugs.
|
||||
*/
|
||||
if (reg > rambits)
|
||||
rambits = reg;
|
||||
if (reg < rambits)
|
||||
printk_err("ERROR! register 0x%x is not set!\n",
|
||||
ramregs[i]);
|
||||
}
|
||||
|
||||
printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*8*1024);
|
||||
mem[0].sizek = rambits*8*1024;
|
||||
#if 1
|
||||
for(i = 0; i < idx; i++) {
|
||||
printk_debug("mem[%d].basek = %08x mem[%d].sizek = %08x\n",
|
||||
i, mem[i].basek, i, mem[i].sizek);
|
||||
}
|
||||
#endif
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
/*
|
||||
* This fixup is based on capturing values from an Award bios. Without
|
||||
* this fixup the DMA write performance is awful (i.e. hdparm -t /dev/hda is 20x
|
||||
* slower than normal, ethernet drops packets).
|
||||
* Apparently these registers govern some sort of bus master behavior.
|
||||
*/
|
||||
static void random_fixup() {
|
||||
device_t pcidev = dev_find_slot(0, 0);
|
||||
|
||||
static void northbridge_init(device_t dev)
|
||||
{
|
||||
printk_spew("VT8601 random fixup ...\n");
|
||||
if (pcidev) {
|
||||
pci_write_config8(pcidev, 0x70, 0xc0);
|
||||
pci_write_config8(pcidev, 0x71, 0x88);
|
||||
pci_write_config8(pcidev, 0x72, 0xec);
|
||||
pci_write_config8(pcidev, 0x73, 0x0c);
|
||||
pci_write_config8(pcidev, 0x74, 0x0e);
|
||||
pci_write_config8(pcidev, 0x75, 0x81);
|
||||
pci_write_config8(pcidev, 0x76, 0x52);
|
||||
}
|
||||
pci_write_config8(dev, 0x70, 0xc0);
|
||||
pci_write_config8(dev, 0x71, 0x88);
|
||||
pci_write_config8(dev, 0x72, 0xec);
|
||||
pci_write_config8(dev, 0x73, 0x0c);
|
||||
pci_write_config8(dev, 0x74, 0x0e);
|
||||
pci_write_config8(dev, 0x75, 0x81);
|
||||
pci_write_config8(dev, 0x76, 0x52);
|
||||
}
|
||||
|
||||
static void northbridge_init(struct chip *chip, enum chip_pass pass)
|
||||
|
||||
|
||||
static struct device_operations northbridge_operations = {
|
||||
.read_resources = pci_dev_read_resources,
|
||||
.set_resources = pci_dev_set_resources,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = northbridge_init,
|
||||
.enable = 0,
|
||||
.ops_pci = 0,
|
||||
};
|
||||
|
||||
static struct pci_driver northbridge_driver __pci_driver = {
|
||||
.ops = &northbridge_operations,
|
||||
.vendor = PCI_VENDOR_ID_VIA,
|
||||
.device = 0x0601, /* 0x8601 is the AGP bridge? */
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define BRIDGE_IO_MASK (IORESOURCE_IO | IORESOURCE_MEM)
|
||||
|
||||
static void pci_domain_read_resources(device_t dev)
|
||||
{
|
||||
struct resource *resource;
|
||||
unsigned reg;
|
||||
|
||||
struct northbridge_via_vt8601_config *conf =
|
||||
(struct northbridge_via_vt8601_config *)chip->chip_info;
|
||||
/* Initialize the system wide io space constraints */
|
||||
resource = new_resource(dev, 0);
|
||||
resource->base = 0x400;
|
||||
resource->limit = 0xffffUL;
|
||||
resource->flags = IORESOURCE_IO;
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
IORESOURCE_IO, IORESOURCE_IO);
|
||||
|
||||
switch (pass) {
|
||||
case CONF_PASS_PRE_PCI:
|
||||
break;
|
||||
|
||||
case CONF_PASS_POST_PCI:
|
||||
break;
|
||||
|
||||
case CONF_PASS_PRE_BOOT:
|
||||
random_fixup();
|
||||
break;
|
||||
|
||||
default:
|
||||
/* nothing yet */
|
||||
break;
|
||||
/* Initialize the system wide memory resources constraints */
|
||||
resource = new_resource(dev, 1);
|
||||
resource->limit = 0xffffffffULL;
|
||||
resource->flags = IORESOURCE_MEM;
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
IORESOURCE_MEM, IORESOURCE_MEM);
|
||||
}
|
||||
|
||||
static void ram_resource(device_t dev, unsigned long index,
|
||||
unsigned long basek, unsigned long sizek)
|
||||
{
|
||||
struct resource *resource;
|
||||
|
||||
if (!sizek) {
|
||||
return;
|
||||
}
|
||||
resource = new_resource(dev, index);
|
||||
resource->base = ((resource_t)basek) << 10;
|
||||
resource->size = ((resource_t)sizek) << 10;
|
||||
resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE | \
|
||||
IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
|
||||
}
|
||||
|
||||
static const uint8_t ramregs[] = {0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
|
||||
0x56, 0x57};
|
||||
|
||||
static void pci_domain_set_resources(device_t dev)
|
||||
{
|
||||
struct resource *resource, *last;
|
||||
device_t mc_dev;
|
||||
uint32_t pci_tolm;
|
||||
|
||||
pci_tolm = 0xffffffffUL;
|
||||
last = &dev->resource[dev->resources];
|
||||
for(resource = &dev->resource[0]; resource < last; resource++)
|
||||
{
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
BRIDGE_IO_MASK, resource->flags & BRIDGE_IO_MASK);
|
||||
|
||||
resource->flags |= IORESOURCE_STORED;
|
||||
report_resource_stored(dev, resource, "");
|
||||
|
||||
if ((resource->flags & IORESOURCE_MEM) &&
|
||||
(pci_tolm > resource->base))
|
||||
{
|
||||
pci_tolm = resource->base;
|
||||
}
|
||||
}
|
||||
|
||||
mc_dev = dev->link[0].children;
|
||||
if (mc_dev) {
|
||||
unsigned long tomk, tolmk;
|
||||
unsigned char rambits;
|
||||
int i, idx;
|
||||
|
||||
for(rambits = 0, i = 0; i < sizeof(ramregs)/sizeof(ramregs[0]); i++) {
|
||||
unsigned char reg;
|
||||
reg = pci_read_config8(mc_dev, ramregs[i]);
|
||||
/* these are ENDING addresses, not sizes.
|
||||
* if there is memory in this slot, then reg will be > rambits.
|
||||
* So we just take the max, that gives us total.
|
||||
* We take the highest one to cover for once and future linuxbios
|
||||
* bugs. We warn about bugs.
|
||||
*/
|
||||
if (reg > rambits)
|
||||
rambits = reg;
|
||||
if (reg < rambits)
|
||||
printk_err("ERROR! register 0x%x is not set!\n",
|
||||
ramregs[i]);
|
||||
}
|
||||
printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*8*1024);
|
||||
tomk = ramreg*8*1024;
|
||||
/* Compute the top of Low memory */
|
||||
tolmk = pci_tolm >> 10;
|
||||
if (tolmk >= tomk) {
|
||||
/* The PCI hole does does not overlap the memory.
|
||||
*/
|
||||
tolmk = tomk;
|
||||
}
|
||||
/* Report the memory regions */
|
||||
idx = 10;
|
||||
ram_resource(dev, idx++, 0, tolmk);
|
||||
}
|
||||
assign_resources(&dev->link[0]);
|
||||
}
|
||||
|
||||
static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
|
||||
{
|
||||
max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
|
||||
return max;
|
||||
}
|
||||
|
||||
static struct device_operations pci_domain_ops = {
|
||||
.read_resources = pci_domain_read_resources,
|
||||
.set_resources = pci_domain_set_resources,
|
||||
.enable_resources = enable_childrens_resources,
|
||||
.init = 0,
|
||||
.scan_bus = pci_domain_scan_bus,
|
||||
};
|
||||
|
||||
static void cpu_bus_init(device_t dev)
|
||||
{
|
||||
initialize_cpus(&dev->link[0]);
|
||||
}
|
||||
|
||||
static void cpu_bus_noop(device_t dev)
|
||||
{
|
||||
}
|
||||
|
||||
static struct device_operations cpu_bus_ops = {
|
||||
.read_resources = cpu_bus_noop,
|
||||
.set_resources = cpu_bus_noop,
|
||||
.enable_resources = cpu_bus_noop,
|
||||
.init = cpu_bus_init,
|
||||
.scan_bus = 0,
|
||||
};
|
||||
|
||||
static void enable_dev(struct device *dev)
|
||||
{
|
||||
struct device_path path;
|
||||
|
||||
/* Set the operations if it is a special bus type */
|
||||
if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
|
||||
dev->ops = &pci_domain_ops;
|
||||
}
|
||||
else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
|
||||
dev->ops = &cpu_bus_ops;
|
||||
}
|
||||
}
|
||||
|
||||
struct chip_operations northbridge_via_vt8601_control = {
|
||||
.enable = northbridge_init,
|
||||
.enable_dev = enable_dev,
|
||||
.name = "VIA vt8601 Northbridge",
|
||||
};
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
#include <console/console.h>
|
||||
#include <arch/io.h>
|
||||
#include <stdint.h>
|
||||
#include <mem.h>
|
||||
#include <part/sizeram.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/hypertransport.h>
|
||||
|
@ -14,151 +12,267 @@
|
|||
#include "chip.h"
|
||||
#include "northbridge.h"
|
||||
|
||||
static const uint8_t ramregs[] = {0x5a, 0x5b, 0x5c, 0x5d };
|
||||
|
||||
struct mem_range *sizeram(void)
|
||||
{
|
||||
unsigned long mmio_basek;
|
||||
static struct mem_range mem[10];
|
||||
device_t dev;
|
||||
int i, idx;
|
||||
unsigned char rambits;
|
||||
|
||||
dev = dev_find_slot(0, 0);
|
||||
if (!dev) {
|
||||
printk_err("Cannot find PCI: 0:0\n");
|
||||
return 0;
|
||||
}
|
||||
mem[0].basek = 0;
|
||||
mem[0].sizek = 0xa0000 >>10; // first 640k
|
||||
mem[1].basek = 0xc0000 >>10; // leave a hole for vga
|
||||
idx = 2;
|
||||
while(idx < sizeof(mem)/sizeof(mem[0])) {
|
||||
mem[idx].basek = 0;
|
||||
mem[idx].sizek = 0;
|
||||
idx++;
|
||||
}
|
||||
for(rambits = 0, i = 0; i < sizeof(ramregs)/sizeof(ramregs[0]); i++) {
|
||||
unsigned char reg;
|
||||
reg = pci_read_config8(dev, ramregs[i]);
|
||||
/* these are ENDING addresses, not sizes.
|
||||
* if there is memory in this slot, then reg will be > rambits.
|
||||
* So we just take the max, that gives us total.
|
||||
* We take the highest one to cover for once and future linuxbios
|
||||
* bugs. We warn about bugs.
|
||||
*/
|
||||
if (reg > rambits)
|
||||
rambits = reg;
|
||||
if (reg < rambits)
|
||||
printk_err("ERROR! register 0x%x is not set!\n",
|
||||
ramregs[i]);
|
||||
}
|
||||
|
||||
printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*16*1024);
|
||||
mem[1].sizek = rambits*16*1024 - 32768 - (0xc0000 >> 10);
|
||||
#if 1
|
||||
for(i = 0; i < idx; i++) {
|
||||
printk_debug("mem[%d].basek = %08x mem[%d].sizek = %08x\n",
|
||||
i, mem[i].basek, i, mem[i].sizek);
|
||||
}
|
||||
#endif
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
||||
/*
|
||||
* This fixup is based on capturing values from an Award bios. Without
|
||||
* this fixup the DMA write performance is awful (i.e. hdparm -t /dev/hda is 20x
|
||||
* slower than normal, ethernet drops packets).
|
||||
* Apparently these registers govern some sort of bus master behavior.
|
||||
*/
|
||||
static void random_fixup() {
|
||||
device_t pcidev0 = dev_find_slot(0, 0);
|
||||
device_t pcidev1,pcidev2;
|
||||
static void norhbrige_init(device_t dev)
|
||||
{
|
||||
device_t fb_dev;
|
||||
unsigned long fb;
|
||||
unsigned char c;
|
||||
|
||||
printk_debug("VT8623 random fixup ...\n");
|
||||
if (pcidev0) {
|
||||
pci_write_config8(pcidev0, 0x0d, 0x08);
|
||||
pci_write_config8(pcidev0, 0x70, 0x82);
|
||||
pci_write_config8(pcidev0, 0x71, 0xc8);
|
||||
pci_write_config8(pcidev0, 0x72, 0x0);
|
||||
pci_write_config8(pcidev0, 0x73, 0x01);
|
||||
pci_write_config8(pcidev0, 0x74, 0x01);
|
||||
pci_write_config8(pcidev0, 0x75, 0x08);
|
||||
pci_write_config8(pcidev0, 0x76, 0x52);
|
||||
pci_write_config8(pcidev0, 0x13, 0xd0);
|
||||
pci_write_config8(pcidev0, 0x84, 0x80);
|
||||
pci_write_config16(pcidev0,0x80, 0x610f);
|
||||
pci_write_config32(pcidev0,0x88, 0x02);
|
||||
}
|
||||
printk_debug("VT8623 AGP random fixup ...\n");
|
||||
pcidev1 = dev_find_device(PCI_VENDOR_ID_VIA,0xb091,0);
|
||||
if( pcidev1) {
|
||||
pci_write_config8(pcidev1,0x3e,0x0c);
|
||||
pci_write_config8(pcidev1,0x40,0x83);
|
||||
pci_write_config8(pcidev1,0x41,0xc5);
|
||||
pci_write_config8(pcidev1,0x43,0x44);
|
||||
pci_write_config8(pcidev1,0x44,0x34);
|
||||
pci_write_config8(pcidev1,0x83,0x02);
|
||||
}
|
||||
printk_debug("VGA random fixup ...\n");
|
||||
pcidev2 = dev_find_device(PCI_VENDOR_ID_VIA,0x3122,0);
|
||||
if( pcidev2 ){
|
||||
pci_write_config8(pcidev2,0x04,0x07);
|
||||
pci_write_config8(pcidev2,0x0d,0x20);
|
||||
}
|
||||
// fixup GART and framebuffer addresses properly
|
||||
// first set up frame buffer properly
|
||||
fb = pci_read_config32(pcidev2,0x10); // base address of framebuffer
|
||||
printk_debug("Frame buffer at %8x\n",fb);
|
||||
c = pci_read_config8(pcidev0,0xe1) & 0xf0; // size of vga
|
||||
c |= fb>>28; // upper nibble of frame buffer address
|
||||
pci_write_config8(pcidev0,0xe1,c);
|
||||
c = (fb>>20) | 1; // enable framebuffer
|
||||
pci_write_config8(pcidev0,0xe0,c);
|
||||
pci_write_config8(pcidev0,0xe2,0x42); // 'cos award does
|
||||
|
||||
pci_write_config8(dev, 0x0d, 0x08);
|
||||
pci_write_config8(dev, 0x70, 0x82);
|
||||
pci_write_config8(dev, 0x71, 0xc8);
|
||||
pci_write_config8(dev, 0x72, 0x00);
|
||||
pci_write_config8(dev, 0x73, 0x01);
|
||||
pci_write_config8(dev, 0x74, 0x01);
|
||||
pci_write_config8(dev, 0x75, 0x08);
|
||||
pci_write_config8(dev, 0x76, 0x52);
|
||||
pci_write_config8(dev, 0x13, 0xd0);
|
||||
pci_write_config8(dev, 0x84, 0x80);
|
||||
pci_write_config16(dev, 0x80, 0x610f);
|
||||
pci_write_config32(dev, 0x88, 0x00000002);
|
||||
|
||||
fb_dev = dev_find_device(PCI_VENDOR_ID_VIA, 0x3122, 0);
|
||||
if (fb_dev) {
|
||||
/* Fixup GART and framebuffer addresses properly.
|
||||
* First setup frame buffer properly.
|
||||
*/
|
||||
fb = pci_read_config32(dev, 0x10); /* Base addres of framebuffer */
|
||||
printk_debug("Frame buffer at %8x\n",fb);
|
||||
|
||||
c = pci_read_config8(dev, 0xe1) & 0xf0; /* size of vga */
|
||||
c |= fb>>28; /* upper nibble of frame buffer address */
|
||||
pci_write_config8(dev, 0xe1, c);
|
||||
c = (fb>>20) | 1; /* enable framebuffer */
|
||||
pci_write_config8(dev, 0xe0, c);
|
||||
pci_write_config8(dev, 0xe2, 0x42); /* 'cos award does */
|
||||
}
|
||||
}
|
||||
static void set_vga_mtrrs(void)
|
||||
|
||||
|
||||
static struct device_operations northbridge_operations = {
|
||||
.read_resources = pci_dev_read_resources,
|
||||
.set_resources = pci_dev_set_resources,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = northbridge_init,
|
||||
.scan_bus = pci_scan_bridge,
|
||||
.ops_pci = 0,
|
||||
};
|
||||
|
||||
static struct pci_driver northbridge_driver __pci_driver = {
|
||||
.ops = &northbridge_ops,
|
||||
.vendor = PCI_VENDOR_ID_VIA,
|
||||
.device = 0x3123,
|
||||
};
|
||||
|
||||
static void agp_init(device_t dev)
|
||||
{
|
||||
printk_debug("VT8623 AGP random fixup ...\n");
|
||||
|
||||
pci_write_config8(dev, 0x3e, 0x0c);
|
||||
pci_write_config8(dev, 0x40, 0x83);
|
||||
pci_write_config8(dev, 0x41, 0xc5);
|
||||
pci_write_config8(dev, 0x43, 0x44);
|
||||
pci_write_config8(dev, 0x44, 0x34);
|
||||
pci_write_config8(dev, 0x83, 0x02);
|
||||
}
|
||||
|
||||
static struct device_operations agp_operations = {
|
||||
.read_resources = pci_bus_read_resources,
|
||||
.set_resources = pci_dev_set_resources,
|
||||
.enable_resources = pci_bus_enable_resources,
|
||||
.init = agp_init,
|
||||
.scan_bus = pci_scan_bridge,
|
||||
.ops_pci = 0,
|
||||
};
|
||||
|
||||
static struct pci_driver agp_driver __pci_driver = {
|
||||
.ops = &agp_ops,
|
||||
.vendor = PCI_VENDOR_ID_VIA,
|
||||
.device = 0xb091,
|
||||
};
|
||||
|
||||
static void vga_init(device_t dev)
|
||||
{
|
||||
device_t pcidev = dev_find_device(PCI_VENDOR_ID_VIA,0x3122,0);
|
||||
unsigned long fb;
|
||||
|
||||
add_var_mtrr( 0xd0000000 >> 10, 0x08000000>>10, MTRR_TYPE_WRCOMB);
|
||||
fb = pci_read_config32(pcidev,0x10); // get the fb address
|
||||
add_var_mtrr( fb>>10, 8192, MTRR_TYPE_WRCOMB);
|
||||
printk_debug("VGA random fixup ...\n");
|
||||
pci_write_config8(dev, 0x04, 0x07);
|
||||
pci_write_config8(dev, 0x0d, 0x20);
|
||||
|
||||
|
||||
/* Set the vga mtrrs */
|
||||
add_var_mtrr( 0xd0000000 >> 10, 0x08000000>>10, MTRR_TYPE_WRCOMB);
|
||||
fb = pci_read_config32(dev,0x10); // get the fb address
|
||||
add_var_mtrr( fb>>10, 8192, MTRR_TYPE_WRCOMB);
|
||||
}
|
||||
|
||||
static void northbridge_init(struct chip *chip, enum chip_pass pass)
|
||||
static struct device_operations vga_operations = {
|
||||
.read_resources = pci_dev_read_resources,
|
||||
.set_resources = pci_dev_set_resources,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = vga_init,
|
||||
.ops_pci = 0,
|
||||
};
|
||||
|
||||
static struct pci_driver vga_driver __pci_driver = {
|
||||
.ops = &vga_ops,
|
||||
.vendor = PCI_VENDOR_ID_VIA,
|
||||
.device = 0x3122,
|
||||
};
|
||||
|
||||
|
||||
#define BRIDGE_IO_MASK (IORESOURCE_IO | IORESOURCE_MEM)
|
||||
|
||||
static void pci_domain_read_resources(device_t dev)
|
||||
{
|
||||
struct resource *resource;
|
||||
unsigned reg;
|
||||
|
||||
struct northbridge_via_vt8623_config *conf =
|
||||
(struct northbridge_via_vt8623_config *)chip->chip_info;
|
||||
/* Initialize the system wide io space constraints */
|
||||
resource = new_resource(dev, 0);
|
||||
resource->base = 0x400;
|
||||
resource->limit = 0xffffUL;
|
||||
resource->flags = IORESOURCE_IO;
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
IORESOURCE_IO, IORESOURCE_IO);
|
||||
|
||||
switch (pass) {
|
||||
case CONF_PASS_PRE_PCI:
|
||||
break;
|
||||
|
||||
case CONF_PASS_POST_PCI:
|
||||
random_fixup();
|
||||
break;
|
||||
|
||||
case CONF_PASS_PRE_BOOT:
|
||||
set_vga_mtrrs();
|
||||
break;
|
||||
|
||||
default:
|
||||
/* nothing yet */
|
||||
break;
|
||||
/* Initialize the system wide memory resources constraints */
|
||||
resource = new_resource(dev, 1);
|
||||
resource->limit = 0xffffffffULL;
|
||||
resource->flags = IORESOURCE_MEM;
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
IORESOURCE_MEM, IORESOURCE_MEM);
|
||||
}
|
||||
|
||||
static void ram_resource(device_t dev, unsigned long index,
|
||||
unsigned long basek, unsigned long sizek)
|
||||
{
|
||||
struct resource *resource;
|
||||
|
||||
if (!sizek) {
|
||||
return;
|
||||
}
|
||||
resource = new_resource(dev, index);
|
||||
resource->base = ((resource_t)basek) << 10;
|
||||
resource->size = ((resource_t)sizek) << 10;
|
||||
resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE | \
|
||||
IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
|
||||
}
|
||||
|
||||
static const uint8_t ramregs[] = {0x5a, 0x5b, 0x5c, 0x5d };
|
||||
|
||||
static void pci_domain_set_resources(device_t dev)
|
||||
{
|
||||
struct resource *resource, *last;
|
||||
device_t mc_dev;
|
||||
uint32_t pci_tolm;
|
||||
|
||||
pci_tolm = 0xffffffffUL;
|
||||
last = &dev->resource[dev->resources];
|
||||
for(resource = &dev->resource[0]; resource < last; resource++)
|
||||
{
|
||||
compute_allocate_resource(&dev->link[0], resource,
|
||||
BRIDGE_IO_MASK, resource->flags & BRIDGE_IO_MASK);
|
||||
|
||||
resource->flags |= IORESOURCE_STORED;
|
||||
report_resource_stored(dev, resource, "");
|
||||
|
||||
if ((resource->flags & IORESOURCE_MEM) &&
|
||||
(pci_tolm > resource->base))
|
||||
{
|
||||
pci_tolm = resource->base;
|
||||
}
|
||||
}
|
||||
|
||||
mc_dev = dev->link[0].children;
|
||||
if (mc_dev) {
|
||||
unsigned long tomk, tolmk;
|
||||
unsigned char rambits;
|
||||
int i, idx;
|
||||
|
||||
for(rambits = 0, i = 0; i < sizeof(ramregs)/sizeof(ramregs[0]); i++) {
|
||||
unsigned char reg;
|
||||
reg = pci_read_config8(mc_dev, ramregs[i]);
|
||||
/* these are ENDING addresses, not sizes.
|
||||
* if there is memory in this slot, then reg will be > rambits.
|
||||
* So we just take the max, that gives us total.
|
||||
* We take the highest one to cover for once and future linuxbios
|
||||
* bugs. We warn about bugs.
|
||||
*/
|
||||
if (reg > rambits)
|
||||
rambits = reg;
|
||||
if (reg < rambits)
|
||||
printk_err("ERROR! register 0x%x is not set!\n",
|
||||
ramregs[i]);
|
||||
}
|
||||
printk_debug("I would set ram size to 0x%x Kbytes\n", (rambits)*16*1024);
|
||||
tomk = ramreg*16*1024 - 32768;
|
||||
/* Compute the top of Low memory */
|
||||
tolmk = pci_tolm >> 10;
|
||||
if (tolmk >= tomk) {
|
||||
/* The PCI hole does does not overlap the memory.
|
||||
*/
|
||||
tolmk = tomk;
|
||||
}
|
||||
/* Report the memory regions */
|
||||
idx = 10;
|
||||
ram_resource(dev, idx++, 0, 640); /* first 640k */
|
||||
ram_resource(dev, idx++, 768, tolmk - 768); /* leave a hole for vga */
|
||||
}
|
||||
assign_resources(&dev->link[0]);
|
||||
}
|
||||
|
||||
static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
|
||||
{
|
||||
max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
|
||||
return max;
|
||||
}
|
||||
|
||||
static struct device_operations pci_domain_ops = {
|
||||
.read_resources = pci_domain_read_resources,
|
||||
.set_resources = pci_domain_set_resources,
|
||||
.enable_resources = enable_childrens_resources,
|
||||
.init = 0,
|
||||
.scan_bus = pci_domain_scan_bus,
|
||||
};
|
||||
|
||||
static void cpu_bus_init(device_t dev)
|
||||
{
|
||||
initialize_cpus(&dev->link[0]);
|
||||
}
|
||||
|
||||
static void cpu_bus_noop(device_t dev)
|
||||
{
|
||||
}
|
||||
|
||||
static struct device_operations cpu_bus_ops = {
|
||||
.read_resources = cpu_bus_noop,
|
||||
.set_resources = cpu_bus_noop,
|
||||
.enable_resources = cpu_bus_noop,
|
||||
.init = cpu_bus_init,
|
||||
.scan_bus = 0,
|
||||
};
|
||||
|
||||
static void enable_dev(struct device *dev)
|
||||
{
|
||||
struct device_path path;
|
||||
|
||||
/* Set the operations if it is a special bus type */
|
||||
if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
|
||||
dev->ops = &pci_domain_ops;
|
||||
}
|
||||
else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
|
||||
dev->ops = &cpu_bus_ops;
|
||||
}
|
||||
}
|
||||
|
||||
struct chip_operations northbridge_via_vt8623_control = {
|
||||
.enable = northbridge_init,
|
||||
.name = "VIA vt8623 Northbridge",
|
||||
.enable_dev = enable_dev,
|
||||
.name = "VIA vt8623 Northbridge",
|
||||
};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#include <mem.h>
|
||||
#include <pci.h>
|
||||
#include <arch/io.h>
|
||||
#include <printk.h>
|
||||
|
|
Loading…
Reference in New Issue