ckfwq/linux-3.0.4/arch/mips/loongson/common/mem.c

142 lines
3.4 KiB
C

/*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
#include <linux/ioport.h>
#include <asm/bootinfo.h>
#include <loongson.h>
#include <mem.h>
#include <pci.h>
#ifdef CONFIG_ANDROID_RAM_CONSOLE
struct resource ram_console_res = {
.name = "ram_console",
.start = 0,
.end = 0,
.flags = IORESOURCE_BUSY | IORESOURCE_MEM
};
#endif
void __init prom_init_memory(void)
{
#ifdef CONFIG_ANDROID_RAM_CONSOLE
/* Reserve 64KB memory for Android ram console buffer */
ram_console_res.end = memsize - 1 - 2*1024*1024;
memsize -= 4*1024*1024;
ram_console_res.start = memsize;
printk(KERN_INFO "Reserved contiguous memory: 0x200000@0x%x for ram console\n",(unsigned int)ram_console_res.start);
#endif
add_memory_region(0x0, memsize, BOOT_MEM_RAM);
#ifdef CONFIG_PCI
add_memory_region(memsize, (LOONGSON_PCI_MEM_START - memsize),
BOOT_MEM_RESERVED);
#endif
#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
{
int bit;
bit = fls(memsize + highmemsize);
if (bit != ffs(memsize + highmemsize))
bit += 20;
else
bit = bit + 20 - 1;
/* set cpu window3 to map CPU to DDR: 2G -> 2G */
LOONGSON_ADDRWIN_CPUTODDR(ADDRWIN_WIN3, 0x80000000ul,
0x80000000ul, (1 << bit));
mmiowb();
}
#endif /* !CONFIG_CPU_SUPPORTS_ADDRWINCFG */
#ifdef CONFIG_64BIT
if (highmemsize > 0)
add_memory_region(LOONGSON_HIGHMEM_START,
highmemsize, BOOT_MEM_RAM);
#ifdef CONFIG_PCI
add_memory_region(LOONGSON_PCI_MEM_END + 1, LOONGSON_HIGHMEM_START -
LOONGSON_PCI_MEM_END - 1, BOOT_MEM_RESERVED);
#endif
#endif /* !CONFIG_64BIT */
}
/* override of arch/mips/mm/cache.c: __uncached_access */
int __uncached_access(struct file *file, unsigned long addr)
{
if (file->f_flags & O_DSYNC)
return 1;
return addr >= __pa(high_memory) ||
((addr >= LOONGSON_MMIO_MEM_START) &&
(addr < LOONGSON_MMIO_MEM_END));
}
#ifdef CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED
#include <linux/pci.h>
#include <linux/sched.h>
#include <asm/current.h>
static unsigned long uca_start, uca_end;
pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
unsigned long size, pgprot_t vma_prot)
{
unsigned long offset = pfn << PAGE_SHIFT;
unsigned long end = offset + size;
if (__uncached_access(file, offset)) {
if (uca_start && (offset >= uca_start) &&
(end <= uca_end))
return __pgprot((pgprot_val(vma_prot) &
~_CACHE_MASK) |
_CACHE_UNCACHED_ACCELERATED);
else
return pgprot_noncached(vma_prot);
}
return vma_prot;
}
#ifdef CONFIG_PCI
static int __init find_vga_mem_init(void)
{
struct pci_dev *dev = 0;
struct resource *r;
int idx;
if (uca_start)
return 0;
for_each_pci_dev(dev) {
if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
r = &dev->resource[idx];
if (!r->start && r->end)
continue;
if (r->flags & IORESOURCE_IO)
continue;
if (r->flags & IORESOURCE_MEM) {
uca_start = r->start;
uca_end = r->end;
return 0;
}
}
}
}
return 0;
}
late_initcall(find_vga_mem_init);
#endif
#endif /* !CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED */