Skip to content

Commit

Permalink
MIPS: Loongson: Add basic Loongson 2F support
Browse files Browse the repository at this point in the history
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: Wu Zhangjin <[email protected]>
Cc: [email protected]
Signed-off-by: Ralf Baechle <[email protected]>
  • Loading branch information
lzufalcon authored and ralfbaechle committed Dec 17, 2009
1 parent 937893c commit 6f7a251
Show file tree
Hide file tree
Showing 10 changed files with 197 additions and 20 deletions.
18 changes: 18 additions & 0 deletions arch/mips/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
2 changes: 2 additions & 0 deletions arch/mips/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions arch/mips/include/asm/mach-loongson/dma-coherence.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
84 changes: 83 additions & 1 deletion arch/mips/include/asm/mach-loongson/loongson.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
* Copyright (C) 2009 Lemote, Inc.
* Author: Wu Zhangjin <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -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 */
27 changes: 19 additions & 8 deletions arch/mips/include/asm/mach-loongson/mem.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2009 Lemote, Inc. & Institute of Computing Technology
* Copyright (C) 2009 Lemote, Inc.
* Author: Wu Zhangjin <[email protected]>
*
* This program is free software; you can redistribute it and/or modify it
Expand All @@ -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 */
28 changes: 26 additions & 2 deletions arch/mips/include/asm/mach-loongson/pci.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2008 Zhang Le <[email protected]>
* Copyright (c) 2009 Wu Zhangjin <[email protected]>
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
Expand All @@ -24,14 +25,37 @@

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
#define LOONGSON_PCI_MEM_END (LOONGSON_PCILO1_BASE + 0x04000000 * 2)
/* 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_ */
5 changes: 4 additions & 1 deletion arch/mips/loongson/common/bonito-irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* option) any later version.
*/
#include <linux/interrupt.h>
#include <linux/compiler.h>

#include <loongson.h>

Expand All @@ -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",
};
Expand All @@ -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
}
8 changes: 8 additions & 0 deletions arch/mips/loongson/common/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
33 changes: 25 additions & 8 deletions arch/mips/loongson/common/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
8 changes: 8 additions & 0 deletions arch/mips/loongson/common/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 6f7a251

Please sign in to comment.