Commit 6f7a251a authored by Wu Zhangjin's avatar Wu Zhangjin Committed by Ralf Baechle

MIPS: Loongson: Add basic Loongson 2F support

Loongson 2F has built-in DDR2 and PCI-X controller. The PCI-X controller
has a programming interface similiar to the the FPGA northbridge used on
Loongson 2E.

The main differences between Loongson 2E and Loongson 2F include:

1. Loongson 2F has an extra address window configuration module, which
   is used to map CPU address space to DDR or PCI address space, or map
   the PCI-DMA address space to DDR or LIO address space.

2. Loongson 2F supports 8 levels of software configurable CPu frequency
   which can be configured in the LOONGSON_CHIPCFG0 register.  The coming
   cpufreq and standby support are based on this feature.

Loongson.h abstracts the modules and corresponding methods are abstracted.

Add other Loongson-2F-specific source code including gcc 4.4 support, PCI
memory space, PCI IO space, DMA address.
Signed-off-by: default avatarWu Zhangjin <wuzhangjin@gmail.com>
Cc: linux-mips@linux-mips.org
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 937893cf
......@@ -1073,6 +1073,21 @@ config CPU_LOONGSON2E
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
......@@ -1317,6 +1332,9 @@ config CPU_LOONGSON2
config SYS_HAS_CPU_LOONGSON2E
bool
config SYS_HAS_CPU_LOONGSON2F
bool
config SYS_HAS_CPU_MIPS32_R1
bool
......
......@@ -125,6 +125,8 @@ cflags-$(CONFIG_CPU_TX49XX) += -march=r4600 -Wa,--trap
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
......
......@@ -28,7 +28,11 @@ static inline dma_addr_t plat_map_dma_mem_page(struct device *dev,
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
......@@ -219,4 +219,86 @@ extern void mach_irq_dispatch(unsigned int pending);
#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
......@@ -12,19 +12,30 @@
#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
......@@ -24,7 +25,30 @@
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
......@@ -32,6 +56,6 @@ extern struct pci_ops loongson_pci_ops;
/* 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_ */
......@@ -12,6 +12,7 @@
* option) any later version.
*/
#include <linux/interrupt.h>
#include <linux/compiler.h>
#include <loongson.h>
......@@ -35,7 +36,7 @@ static struct irq_chip bonito_irq_type = {
.unmask = bonito_irq_enable,
};
static struct irqaction dma_timeout_irqaction = {
static struct irqaction __maybe_unused dma_timeout_irqaction = {
.handler = no_action,
.name = "dma_timeout",
};
......@@ -47,5 +48,7 @@ void bonito_irq_init(void)
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
}
......@@ -12,12 +12,20 @@
#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();
......
......@@ -21,14 +21,31 @@ void __init prom_init_memory(void)
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 */
......
......@@ -67,6 +67,14 @@ static void __init setup_pcimap(void)
/* 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)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment