From: Wu Zhangjin <wuzj@xxxxxxxxxx> The main purpose is to uncache accelerate for video memory access Signed-off-by: Wu Zhangjin <wuzhangjin@xxxxxxxxx> --- arch/mips/include/asm/pgtable.h | 13 ++++++++ arch/mips/loongson/Kconfig | 12 +++++++ arch/mips/loongson/common/mem.c | 63 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 0 deletions(-) diff --git a/arch/mips/include/asm/pgtable.h b/arch/mips/include/asm/pgtable.h index 6a0edf7..fdb32a5 100644 --- a/arch/mips/include/asm/pgtable.h +++ b/arch/mips/include/asm/pgtable.h @@ -370,6 +370,19 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma, #include <asm-generic/pgtable.h> /* + * uncache accelerate for video memory access + */ +#ifdef CONFIG_LOONGSON2F +#define __HAVE_PHYS_MEM_ACCESS_PROT + +struct file; +pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot); +int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t *vma_prot); +#endif + +/* * We provide our own get_unmapped area to cope with the virtual aliasing * constraints placed on us by the cache architecture. */ diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig index 9cc817f..3d582cb 100644 --- a/arch/mips/loongson/Kconfig +++ b/arch/mips/loongson/Kconfig @@ -114,3 +114,15 @@ config CS5536_UDC config SYS_HAS_MACH_PROM_INIT_CMDLINE bool + +config UCA_SIZE + hex "Uncache Accelerated Region size" + depends on CPU_LOONGSON2F + default 0x400000 if LEMOTE_YEELOONG2F + default 0x2000000 if LEMOTE_FULOONG2F + help + Uncached Acceleration(UCA) can greatly improve video performance. + Normally the Video memory can be accessed in Uncached Accelerated mode, + other peripheral spaces not. + + Specify a zeroed size to disable this feature. diff --git a/arch/mips/loongson/common/mem.c b/arch/mips/loongson/common/mem.c index 9e0b6e0..7223d82 100644 --- a/arch/mips/loongson/common/mem.c +++ b/arch/mips/loongson/common/mem.c @@ -51,3 +51,66 @@ int __uncached_access(struct file *file, unsigned long addr) ((addr >= LOONGSON_MMIO_MEM_START) && \ (addr < LOONGSON_MMIO_MEM_END)); } + +#if defined(CONFIG_CPU_LOONGSON2F) + +#include <linux/pci.h> +#include <linux/sched.h> +#include <asm/current.h> + +static unsigned long uca_start; +static unsigned long uca_size = CONFIG_UCA_SIZE; + +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_start + uca_size))) + return __pgprot((pgprot_val(vma_prot) & \ + ~_CACHE_MASK) | \ + _CACHE_UNCACHED_ACCELERATED); + else + return pgprot_noncached(vma_prot); + } + return vma_prot; +} + +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 >> 8) == PCI_CLASS_DISPLAY_VGA) { + 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; + + printk(KERN_INFO + "find the frame buffer:start=%lx\n", + uca_start); + + return 0; + } + } + + } + } + return 0; +} + +late_initcall(find_vga_mem_init); +#endif /* !CONFIG_CPU_LOONGSON2F */ -- 1.6.0.4