142d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian/*
242d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian * This program is free software; you can redistribute  it and/or modify it
342d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian * under  the terms of  the GNU General  Public License as published by the
442d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian * Free Software Foundation;  either version 2 of the  License, or (at your
542d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian * option) any later version.
642d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian */
742d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian#include <linux/fs.h>
842d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian#include <linux/fcntl.h>
942d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian#include <linux/mm.h>
1042d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian
11bd92aa013e8fcd17328ec8e060477761cf3380d9Wu Zhangjin#include <asm/bootinfo.h>
12bd92aa013e8fcd17328ec8e060477761cf3380d9Wu Zhangjin
135e983ff654ca3df3007b5b558b5271bb4622afa4Wu Zhangjin#include <loongson.h>
1485749d24bcf90440b10394312e5b1c96d1a62cdbWu Zhangjin#include <mem.h>
15659da2ba3ebf53dc49f7f9a357a1aef046bf3139Wu Zhangjin#include <pci.h>
16bd92aa013e8fcd17328ec8e060477761cf3380d9Wu Zhangjin
17bd92aa013e8fcd17328ec8e060477761cf3380d9Wu Zhangjinvoid __init prom_init_memory(void)
18bd92aa013e8fcd17328ec8e060477761cf3380d9Wu Zhangjin{
1950549bda2d47f419758dac9bc72e2b0eb9077d83Wu Zhangjin	add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
2050549bda2d47f419758dac9bc72e2b0eb9077d83Wu Zhangjin
2150549bda2d47f419758dac9bc72e2b0eb9077d83Wu Zhangjin	add_memory_region(memsize << 20, LOONGSON_PCI_MEM_START - (memsize <<
2250549bda2d47f419758dac9bc72e2b0eb9077d83Wu Zhangjin				20), BOOT_MEM_RESERVED);
23659da2ba3ebf53dc49f7f9a357a1aef046bf3139Wu Zhangjin
2455045ff5557bc804752e84dca5d1b1f1d4bb4e31Wu Zhangjin#ifdef CONFIG_CPU_SUPPORTS_ADDRWINCFG
256f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin	{
266f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin		int bit;
276f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin
286f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin		bit = fls(memsize + highmemsize);
296f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin		if (bit != ffs(memsize + highmemsize))
306f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin			bit += 20;
316f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin		else
326f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin			bit = bit + 20 - 1;
336f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin
346f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin		/* set cpu window3 to map CPU to DDR: 2G -> 2G */
356f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin		LOONGSON_ADDRWIN_CPUTODDR(ADDRWIN_WIN3, 0x80000000ul,
366f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin					  0x80000000ul, (1 << bit));
376f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin		mmiowb();
386f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin	}
3955045ff5557bc804752e84dca5d1b1f1d4bb4e31Wu Zhangjin#endif /* !CONFIG_CPU_SUPPORTS_ADDRWINCFG */
406f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin
4155045ff5557bc804752e84dca5d1b1f1d4bb4e31Wu Zhangjin#ifdef CONFIG_64BIT
426f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin	if (highmemsize > 0)
436f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin		add_memory_region(LOONGSON_HIGHMEM_START,
446f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin				  highmemsize << 20, BOOT_MEM_RAM);
456f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin
466f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin	add_memory_region(LOONGSON_PCI_MEM_END + 1, LOONGSON_HIGHMEM_START -
476f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin			  LOONGSON_PCI_MEM_END - 1, BOOT_MEM_RESERVED);
486f7a251a259e5bf58a9ff334bdcfa3e42b6cb7a3Wu Zhangjin
4955045ff5557bc804752e84dca5d1b1f1d4bb4e31Wu Zhangjin#endif /* !CONFIG_64BIT */
50bd92aa013e8fcd17328ec8e060477761cf3380d9Wu Zhangjin}
51bd92aa013e8fcd17328ec8e060477761cf3380d9Wu Zhangjin
5242d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian/* override of arch/mips/mm/cache.c: __uncached_access */
5342d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tianint __uncached_access(struct file *file, unsigned long addr)
5442d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian{
556b2f3d1f769be5779b479c37800229d9a4809fc3Christoph Hellwig	if (file->f_flags & O_DSYNC)
5642d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian		return 1;
5742d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian
5842d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian	return addr >= __pa(high_memory) ||
5985749d24bcf90440b10394312e5b1c96d1a62cdbWu Zhangjin		((addr >= LOONGSON_MMIO_MEM_START) &&
6085749d24bcf90440b10394312e5b1c96d1a62cdbWu Zhangjin		 (addr < LOONGSON_MMIO_MEM_END));
6142d226c7248a28ff8c478c06b7e9bd9ef5d73574Songmao Tian}
6222f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin
6322f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin#ifdef CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED
6422f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin
6522f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin#include <linux/pci.h>
6622f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin#include <linux/sched.h>
6722f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin#include <asm/current.h>
6822f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin
6922f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjinstatic unsigned long uca_start, uca_end;
7022f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin
7122f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjinpgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
7222f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin			      unsigned long size, pgprot_t vma_prot)
7322f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin{
7422f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin	unsigned long offset = pfn << PAGE_SHIFT;
7522f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin	unsigned long end = offset + size;
7622f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin
7722f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin	if (__uncached_access(file, offset)) {
78514b6d0c06a5d751259f145d9593b4d084c1cce3Arnaud Patard		if (uca_start && (offset >= uca_start) &&
7922f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin		    (end <= uca_end))
8022f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin			return __pgprot((pgprot_val(vma_prot) &
8122f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin					 ~_CACHE_MASK) |
8222f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin					_CACHE_UNCACHED_ACCELERATED);
8322f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin		else
8422f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin			return pgprot_noncached(vma_prot);
8522f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin	}
8622f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin	return vma_prot;
8722f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin}
8822f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin
8922f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjinstatic int __init find_vga_mem_init(void)
9022f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin{
9122f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin	struct pci_dev *dev = 0;
9222f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin	struct resource *r;
9322f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin	int idx;
9422f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin
9522f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin	if (uca_start)
9622f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin		return 0;
9722f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin
9822f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin	for_each_pci_dev(dev) {
99ff40ad72addb448c1285181820597a17685ee69aRichard LIU		if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
10022f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin			for (idx = 0; idx < PCI_NUM_RESOURCES; idx++) {
10122f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin				r = &dev->resource[idx];
10222f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin				if (!r->start && r->end)
10322f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin					continue;
10422f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin				if (r->flags & IORESOURCE_IO)
10522f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin					continue;
10622f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin				if (r->flags & IORESOURCE_MEM) {
10722f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin					uca_start = r->start;
10822f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin					uca_end = r->end;
10922f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin					return 0;
11022f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin				}
11122f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin			}
11222f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin		}
11322f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin	}
11422f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin
11522f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin	return 0;
11622f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin}
11722f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin
11822f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjinlate_initcall(find_vga_mem_init);
11922f1fdfd62a5f6ab738ffe03dc2ee9f1f25dabc4Wu Zhangjin#endif /* !CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED */
120