The Loongson 2E processor implements the MIPS III instruction set
          with many extensions.
 
+         It has an internal FPGA northbridge, which is compatiable to
+         bonito64.
+
+config CPU_LOONGSON2F
+       bool "Loongson 2F"
+       depends on SYS_HAS_CPU_LOONGSON2F
+       select CPU_LOONGSON2
+       help
+         The Loongson 2F processor implements the MIPS III instruction set
+         with many extensions.
+
+         Loongson2F have built-in DDR2 and PCIX controller. The PCIX controller
+         have a similar programming interface with FPGA northbridge used in
+         Loongson2E.
+
 config CPU_MIPS32_R1
        bool "MIPS32 Release 1"
        depends on SYS_HAS_CPU_MIPS32_R1
 config SYS_HAS_CPU_LOONGSON2E
        bool
 
+config SYS_HAS_CPU_LOONGSON2F
+       bool
+
 config SYS_HAS_CPU_MIPS32_R1
        bool
 
 
 cflags-$(CONFIG_CPU_LOONGSON2) += -Wa,--trap
 cflags-$(CONFIG_CPU_LOONGSON2E) += \
        $(call cc-option,-march=loongson2e,-march=r4600)
+cflags-$(CONFIG_CPU_LOONGSON2F) += \
+       $(call cc-option,-march=loongson2f,-march=r4600)
 
 cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
                        -Wa,-mips32 -Wa,--trap
 
 static inline unsigned long plat_dma_addr_to_phys(struct device *dev,
        dma_addr_t dma_addr)
 {
+#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+       return (dma_addr > 0x8fffffff) ? dma_addr : (dma_addr & 0x0fffffff);
+#else
        return dma_addr & 0x7fffffff;
+#endif
 }
 
 static inline void plat_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr,
 
 /*
- * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Copyright (C) 2009 Lemote, Inc.
  * Author: Wu Zhangjin <wuzj@lemote.com>
  *
  * This program is free software; you can redistribute  it and/or modify it
 #define LOONGSON_PCIMAP_WIN(WIN, ADDR) \
        ((((ADDR)>>26) & LOONGSON_PCIMAP_PCIMAP_LO0) << ((WIN)*6))
 
+/* Chip Config */
+#ifdef CONFIG_CPU_LOONGSON2F
+#define LOONGSON_CHIPCFG0              LOONGSON_REG(LOONGSON_REGBASE + 0x80)
+#endif
+
+/*
+ * address windows configuration module
+ *
+ * loongson2e do not have this module
+ */
+#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+
+/* address window config module base address */
+#define LOONGSON_ADDRWINCFG_BASE               0x3ff00000ul
+#define LOONGSON_ADDRWINCFG_SIZE               0x180
+
+extern unsigned long _loongson_addrwincfg_base;
+#define LOONGSON_ADDRWINCFG(offset) \
+       (*(volatile u64 *)(_loongson_addrwincfg_base + (offset)))
+
+#define CPU_WIN0_BASE  LOONGSON_ADDRWINCFG(0x00)
+#define CPU_WIN1_BASE  LOONGSON_ADDRWINCFG(0x08)
+#define CPU_WIN2_BASE  LOONGSON_ADDRWINCFG(0x10)
+#define CPU_WIN3_BASE  LOONGSON_ADDRWINCFG(0x18)
+
+#define CPU_WIN0_MASK  LOONGSON_ADDRWINCFG(0x20)
+#define CPU_WIN1_MASK  LOONGSON_ADDRWINCFG(0x28)
+#define CPU_WIN2_MASK  LOONGSON_ADDRWINCFG(0x30)
+#define CPU_WIN3_MASK  LOONGSON_ADDRWINCFG(0x38)
+
+#define CPU_WIN0_MMAP  LOONGSON_ADDRWINCFG(0x40)
+#define CPU_WIN1_MMAP  LOONGSON_ADDRWINCFG(0x48)
+#define CPU_WIN2_MMAP  LOONGSON_ADDRWINCFG(0x50)
+#define CPU_WIN3_MMAP  LOONGSON_ADDRWINCFG(0x58)
+
+#define PCIDMA_WIN0_BASE       LOONGSON_ADDRWINCFG(0x60)
+#define PCIDMA_WIN1_BASE       LOONGSON_ADDRWINCFG(0x68)
+#define PCIDMA_WIN2_BASE       LOONGSON_ADDRWINCFG(0x70)
+#define PCIDMA_WIN3_BASE       LOONGSON_ADDRWINCFG(0x78)
+
+#define PCIDMA_WIN0_MASK       LOONGSON_ADDRWINCFG(0x80)
+#define PCIDMA_WIN1_MASK       LOONGSON_ADDRWINCFG(0x88)
+#define PCIDMA_WIN2_MASK       LOONGSON_ADDRWINCFG(0x90)
+#define PCIDMA_WIN3_MASK       LOONGSON_ADDRWINCFG(0x98)
+
+#define PCIDMA_WIN0_MMAP       LOONGSON_ADDRWINCFG(0xa0)
+#define PCIDMA_WIN1_MMAP       LOONGSON_ADDRWINCFG(0xa8)
+#define PCIDMA_WIN2_MMAP       LOONGSON_ADDRWINCFG(0xb0)
+#define PCIDMA_WIN3_MMAP       LOONGSON_ADDRWINCFG(0xb8)
+
+#define ADDRWIN_WIN0   0
+#define ADDRWIN_WIN1   1
+#define ADDRWIN_WIN2   2
+#define ADDRWIN_WIN3   3
+
+#define ADDRWIN_MAP_DST_DDR    0
+#define ADDRWIN_MAP_DST_PCI    1
+#define ADDRWIN_MAP_DST_LIO    1
+
+/*
+ * s: CPU, PCIDMA
+ * d: DDR, PCI, LIO
+ * win: 0, 1, 2, 3
+ * src: map source
+ * dst: map destination
+ * size: ~mask + 1
+ */
+#define LOONGSON_ADDRWIN_CFG(s, d, w, src, dst, size) do {\
+       s##_WIN##w##_BASE = (src); \
+       s##_WIN##w##_MMAP = (src) | ADDRWIN_MAP_DST_##d; \
+       s##_WIN##w##_MASK = ~(size-1); \
+} while (0)
+
+#define LOONGSON_ADDRWIN_CPUTOPCI(win, src, dst, size) \
+       LOONGSON_ADDRWIN_CFG(CPU, PCI, win, src, dst, size)
+#define LOONGSON_ADDRWIN_CPUTODDR(win, src, dst, size) \
+       LOONGSON_ADDRWIN_CFG(CPU, DDR, win, src, dst, size)
+#define LOONGSON_ADDRWIN_PCITODDR(win, src, dst, size) \
+       LOONGSON_ADDRWIN_CFG(PCIDMA, DDR, win, src, dst, size)
+
+#endif /* ! CONFIG_CPU_LOONGSON2F && CONFIG_64BIT */
+
 #endif /* __ASM_MACH_LOONGSON_LOONGSON_H */
 
 /*
- * Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
+ * Copyright (C) 2009 Lemote, Inc.
  * Author: Wu Zhangjin <wuzj@lemote.com>
  *
  * This program is free software; you can redistribute  it and/or modify it
 #define __ASM_MACH_LOONGSON_MEM_H
 
 /*
- * On Lemote Loongson 2e
+ * high memory space
  *
- * the high memory space starts from 512M.
- * the peripheral registers reside between 0x1000:0000 and 0x2000:0000.
+ * in loongson2e, starts from 512M
+ * in loongson2f, starts from 2G 256M
  */
+#ifdef CONFIG_CPU_LOONGSON2E
+#define LOONGSON_HIGHMEM_START 0x20000000
+#else
+#define LOONGSON_HIGHMEM_START 0x90000000
+#endif
 
-#ifdef CONFIG_LEMOTE_FULOONG2E
-
-#define LOONGSON_HIGHMEM_START  0x20000000
+/*
+ * the peripheral registers(MMIO):
+ *
+ * On the Lemote Loongson 2e system, reside between 0x1000:0000 and 0x2000:0000.
+ * On the Lemote Loongson 2f system, reside between 0x1000:0000 and 0x8000:0000.
+ */
 
 #define LOONGSON_MMIO_MEM_START 0x10000000
-#define LOONGSON_MMIO_MEM_END   0x20000000
 
+#ifdef CONFIG_CPU_LOONGSON2E
+#define LOONGSON_MMIO_MEM_END  0x20000000
+#else
+#define LOONGSON_MMIO_MEM_END  0x80000000
 #endif
 
 #endif /* __ASM_MACH_LOONGSON_MEM_H */
 
 /*
  * Copyright (c) 2008 Zhang Le <r0bertz@gentoo.org>
+ * Copyright (c) 2009 Wu Zhangjin <wuzj@lemote.com>
  *
  * This program is free software; you can redistribute it
  * and/or modify it under the terms of the GNU General
 
 extern struct pci_ops loongson_pci_ops;
 
-#ifdef CONFIG_LEMOTE_FULOONG2E
+/* this is an offset from mips_io_port_base */
+#define LOONGSON_PCI_IO_START  0x00004000UL
+
+#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+
+/*
+ * we use address window2 to map cpu address space to pci space
+ * window2: cpu [1G, 2G] -> pci [1G, 2G]
+ * why not use window 0 & 1? because they are used by cpu when booting.
+ * window0: cpu [0, 256M] -> ddr [0, 256M]
+ * window1: cpu [256M, 512M] -> pci [256M, 512M]
+ */
+
+/* the smallest LOONGSON_CPU_MEM_SRC can be 512M */
+#define LOONGSON_CPU_MEM_SRC   0x40000000ul            /* 1G */
+#define LOONGSON_PCI_MEM_DST   LOONGSON_CPU_MEM_SRC
+
+#define LOONGSON_PCI_MEM_START LOONGSON_PCI_MEM_DST
+#define LOONGSON_PCI_MEM_END   (0x80000000ul-1)        /* 2G */
+
+#define MMAP_CPUTOPCI_SIZE     (LOONGSON_PCI_MEM_END - \
+                                       LOONGSON_PCI_MEM_START + 1)
+
+#else  /* loongson2f/32bit & loongson2e */
 
 /* this pci memory space is mapped by pcimap in pci.c */
 #define LOONGSON_PCI_MEM_START LOONGSON_PCILO1_BASE
 /* this is an offset from mips_io_port_base */
 #define LOONGSON_PCI_IO_START  0x00004000UL
 
-#endif
+#endif /* !(defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT))*/
 
 #endif /* !__ASM_MACH_LOONGSON_PCI_H_ */
 
  *  option) any later version.
  */
 #include <linux/interrupt.h>
+#include <linux/compiler.h>
 
 #include <loongson.h>
 
        .unmask = bonito_irq_enable,
 };
 
-static struct irqaction dma_timeout_irqaction = {
+static struct irqaction __maybe_unused dma_timeout_irqaction = {
        .handler        = no_action,
        .name           = "dma_timeout",
 };
        for (i = LOONGSON_IRQ_BASE; i < LOONGSON_IRQ_BASE + 32; i++)
                set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq);
 
+#ifdef CONFIG_CPU_LOONGSON2E
        setup_irq(LOONGSON_IRQ_BASE + 10, &dma_timeout_irqaction);
+#endif
 }
 
 
 #include <loongson.h>
 
+/* Loongson CPU address windows config space base address */
+unsigned long __maybe_unused _loongson_addrwincfg_base;
+
 void __init prom_init(void)
 {
        /* init base address of io space */
        set_io_port_base((unsigned long)
                ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
 
+#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+       _loongson_addrwincfg_base = (unsigned long)
+               ioremap(LOONGSON_ADDRWINCFG_BASE, LOONGSON_ADDRWINCFG_SIZE);
+#endif
+
        prom_init_cmdline();
        prom_init_env();
        prom_init_memory();
 
     add_memory_region(memsize << 20, LOONGSON_PCI_MEM_START - (memsize <<
                            20), BOOT_MEM_RESERVED);
 #ifdef CONFIG_64BIT
-    if (highmemsize > 0)
-       add_memory_region(LOONGSON_HIGHMEM_START,
-               highmemsize << 20, BOOT_MEM_RAM);
-
-    add_memory_region(LOONGSON_PCI_MEM_END + 1, LOONGSON_HIGHMEM_START -
-                   LOONGSON_PCI_MEM_END - 1, BOOT_MEM_RESERVED);
-
-#endif /* CONFIG_64BIT */
+#ifdef CONFIG_CPU_LOONGSON2F
+       {
+               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_LOONGSON2F */
+
+       if (highmemsize > 0)
+               add_memory_region(LOONGSON_HIGHMEM_START,
+                                 highmemsize << 20, BOOT_MEM_RAM);
+
+       add_memory_region(LOONGSON_PCI_MEM_END + 1, LOONGSON_HIGHMEM_START -
+                         LOONGSON_PCI_MEM_END - 1, BOOT_MEM_RESERVED);
+
+#endif                         /* CONFIG_64BIT */
 }
 
 /* override of arch/mips/mm/cache.c: __uncached_access */
 
        /* can not change gnt to break pci transfer when device's gnt not
        deassert for some broken device */
        LOONGSON_PXARB_CFG = 0x00fe0105ul;
+
+#if defined(CONFIG_CPU_LOONGSON2F) && defined(CONFIG_64BIT)
+       /*
+        * set cpu addr window2 to map CPU address space to PCI address space
+        */
+       LOONGSON_ADDRWIN_CPUTOPCI(ADDRWIN_WIN2, LOONGSON_CPU_MEM_SRC,
+               LOONGSON_PCI_MEM_DST, MMAP_CPUTOPCI_SIZE);
+#endif
 }
 
 static int __init pcibios_init(void)