* [PATCH 1/2] MIPS: Add basic support for Loongson1B (UPDATED)
@ 2011-09-26 9:37 keguang.zhang
2011-09-26 9:37 ` [PATCH 2/2] MIPS: Add defconfig " keguang.zhang
0 siblings, 1 reply; 8+ messages in thread
From: keguang.zhang @ 2011-09-26 9:37 UTC (permalink / raw)
To: linux-mips, linux-kernel; +Cc: ralf, wuzhangjin, r0bertz, chenj, Kelvin Cheung
From: Kelvin Cheung <keguang.zhang@gmail.com>
This patch adds basic support for Loongson1B
including serial port, timer and interrupt handler.
Loongson 1B is a 32-bit SoC designed by Institute of
Computing Technology (ICT), Chinese Academy of Sciences (CAS),
which implements the MIPS32 release 2 instruction set.
Signed-off-by: Kelvin Cheung <keguang.zhang@gmail.com>
---
arch/mips/Kbuild.platforms | 1 +
arch/mips/Kconfig | 31 ++++
arch/mips/include/asm/cpu.h | 3 +-
arch/mips/include/asm/mach-loongson1/irq.h | 70 +++++++++
arch/mips/include/asm/mach-loongson1/loongson1.h | 47 ++++++
arch/mips/include/asm/mach-loongson1/platform.h | 20 +++
arch/mips/include/asm/mach-loongson1/prom.h | 24 +++
arch/mips/include/asm/mach-loongson1/regs-clk.h | 32 ++++
arch/mips/include/asm/mach-loongson1/regs-intc.h | 25 ++++
arch/mips/include/asm/mach-loongson1/regs-wdt.h | 21 +++
arch/mips/include/asm/mach-loongson1/war.h | 25 ++++
arch/mips/include/asm/module.h | 2 +
arch/mips/kernel/cpu-probe.c | 15 ++
arch/mips/kernel/perf_event_mipsxx.c | 6 +
arch/mips/kernel/traps.c | 1 +
arch/mips/loongson1/Kconfig | 21 +++
arch/mips/loongson1/Makefile | 11 ++
arch/mips/loongson1/Platform | 7 +
arch/mips/loongson1/common/Makefile | 5 +
arch/mips/loongson1/common/clock.c | 165 ++++++++++++++++++++++
arch/mips/loongson1/common/irq.c | 136 ++++++++++++++++++
arch/mips/loongson1/common/platform.c | 50 +++++++
arch/mips/loongson1/common/prom.c | 88 ++++++++++++
arch/mips/loongson1/common/reset.c | 46 ++++++
arch/mips/loongson1/common/setup.c | 29 ++++
arch/mips/loongson1/ls1b/Makefile | 5 +
arch/mips/loongson1/ls1b/board.c | 30 ++++
arch/mips/oprofile/common.c | 1 +
arch/mips/oprofile/op_model_mipsxx.c | 4 +
29 files changed, 920 insertions(+), 1 deletions(-)
create mode 100644 arch/mips/include/asm/mach-loongson1/irq.h
create mode 100644 arch/mips/include/asm/mach-loongson1/loongson1.h
create mode 100644 arch/mips/include/asm/mach-loongson1/platform.h
create mode 100644 arch/mips/include/asm/mach-loongson1/prom.h
create mode 100644 arch/mips/include/asm/mach-loongson1/regs-clk.h
create mode 100644 arch/mips/include/asm/mach-loongson1/regs-intc.h
create mode 100644 arch/mips/include/asm/mach-loongson1/regs-wdt.h
create mode 100644 arch/mips/include/asm/mach-loongson1/war.h
create mode 100644 arch/mips/loongson1/Kconfig
create mode 100644 arch/mips/loongson1/Makefile
create mode 100644 arch/mips/loongson1/Platform
create mode 100644 arch/mips/loongson1/common/Makefile
create mode 100644 arch/mips/loongson1/common/clock.c
create mode 100644 arch/mips/loongson1/common/irq.c
create mode 100644 arch/mips/loongson1/common/platform.c
create mode 100644 arch/mips/loongson1/common/prom.c
create mode 100644 arch/mips/loongson1/common/reset.c
create mode 100644 arch/mips/loongson1/common/setup.c
create mode 100644 arch/mips/loongson1/ls1b/Makefile
create mode 100644 arch/mips/loongson1/ls1b/board.c
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index 5ce8029..d64786d 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -14,6 +14,7 @@ platforms += jz4740
platforms += lantiq
platforms += lasat
platforms += loongson
+platforms += loongson1
platforms += mipssim
platforms += mti-malta
platforms += netlogic
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index d9b8ea8..4c6ad4f 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -262,6 +262,17 @@ config MACH_LOONGSON
Chinese Academy of Sciences (CAS) in the People's Republic
of China. The chief architect is Professor Weiwu Hu.
+config MACH_LOONGSON1
+ bool "Loongson1 family of machines"
+ select SYS_SUPPORTS_ZBOOT
+ help
+ This enables the support of Loongson1 family of machines.
+
+ Loongson1 is a family of 32-bit MIPS-compatible SoCs.
+ developed at Institute of Computing Technology (ICT),
+ Chinese Academy of Sciences (CAS) in the People's Republic
+ of China.
+
config MIPS_MALTA
bool "MIPS Malta board"
select ARCH_MAY_HAVE_PC_FDC
@@ -808,6 +819,7 @@ source "arch/mips/txx9/Kconfig"
source "arch/mips/vr41xx/Kconfig"
source "arch/mips/cavium-octeon/Kconfig"
source "arch/mips/loongson/Kconfig"
+source "arch/mips/loongson1/Kconfig"
source "arch/mips/netlogic/Kconfig"
endmenu
@@ -1201,6 +1213,14 @@ config CPU_LOONGSON2F
have a similar programming interface with FPGA northbridge used in
Loongson2E.
+config CPU_LOONGSON1B
+ bool "Loongson 1B"
+ depends on SYS_HAS_CPU_LOONGSON1B
+ select CPU_LOONGSON1
+ help
+ The Loongson 1B is a 32-bit SoC, which implements the MIPS32
+ release 2 instruction set.
+
config CPU_MIPS32_R1
bool "MIPS32 Release 1"
depends on SYS_HAS_CPU_MIPS32_R1
@@ -1529,6 +1549,14 @@ config CPU_LOONGSON2
select CPU_SUPPORTS_64BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
+config CPU_LOONGSON1
+ bool
+ select CPU_MIPS32
+ select CPU_MIPSR2
+ select CPU_HAS_PREFETCH
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_HIGHMEM
+
config SYS_HAS_CPU_LOONGSON2E
bool
@@ -1538,6 +1566,9 @@ config SYS_HAS_CPU_LOONGSON2F
select CPU_SUPPORTS_ADDRWINCFG if 64BIT
select CPU_SUPPORTS_UNCACHED_ACCELERATED
+config SYS_HAS_CPU_LOONGSON1B
+ bool
+
config SYS_HAS_CPU_MIPS32_R1
bool
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 5f95a4b..975f372 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -191,6 +191,7 @@
#define PRID_REV_34K_V1_0_2 0x0022
#define PRID_REV_LOONGSON2E 0x0002
#define PRID_REV_LOONGSON2F 0x0003
+#define PRID_REV_LOONGSON1B 0x0020
/*
* Older processors used to encode processor version and revision in two
@@ -253,7 +254,7 @@ enum cpu_type_enum {
*/
CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
- CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC,
+ CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1,
/*
* MIPS64 class processors
diff --git a/arch/mips/include/asm/mach-loongson1/irq.h b/arch/mips/include/asm/mach-loongson1/irq.h
new file mode 100644
index 0000000..e8fed7a
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/irq.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * IRQ mappings for Loongson1.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+
+#ifndef __ASM_MACH_LOONGSON1_IRQ_H
+#define __ASM_MACH_LOONGSON1_IRQ_H
+
+/*
+ * CPU core Interrupt Numbers
+ */
+#define MIPS_CPU_IRQ_BASE 0
+#define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x))
+#define SOFTINT0_IRQ MIPS_CPU_IRQ(0)
+#define SOFTINT1_IRQ MIPS_CPU_IRQ(1)
+#define INT0_IRQ MIPS_CPU_IRQ(2)
+#define INT1_IRQ MIPS_CPU_IRQ(3)
+#define INT2_IRQ MIPS_CPU_IRQ(4)
+#define INT3_IRQ MIPS_CPU_IRQ(5)
+#define INT4_IRQ MIPS_CPU_IRQ(6)
+#define TIMER_IRQ MIPS_CPU_IRQ(7) /* cpu timer */
+
+/*
+ * INT0~3 Interrupt Numbers
+ */
+#define LOONGSON1_IRQ_BASE 8
+#define LOONGSON1_IRQ(n, x) (LOONGSON1_IRQ_BASE + (n << 5) + (x))
+
+#define LOONGSON1_UART0_IRQ LOONGSON1_IRQ(0, 2)
+#define LOONGSON1_UART1_IRQ LOONGSON1_IRQ(0, 3)
+#define LOONGSON1_UART2_IRQ LOONGSON1_IRQ(0, 4)
+#define LOONGSON1_UART3_IRQ LOONGSON1_IRQ(0, 5)
+#define LOONGSON1_CAN0_IRQ LOONGSON1_IRQ(0, 6)
+#define LOONGSON1_CAN1_IRQ LOONGSON1_IRQ(0, 7)
+#define LOONGSON1_SPI0_IRQ LOONGSON1_IRQ(0, 8)
+#define LOONGSON1_SPI1_IRQ LOONGSON1_IRQ(0, 9)
+#define LOONGSON1_AC97_IRQ LOONGSON1_IRQ(0, 10)
+#define LOONGSON1_DMA0_IRQ LOONGSON1_IRQ(0, 13)
+#define LOONGSON1_DMA1_IRQ LOONGSON1_IRQ(0, 14)
+#define LOONGSON1_DMA2_IRQ LOONGSON1_IRQ(0, 15)
+#define LOONGSON1_PWM0_IRQ LOONGSON1_IRQ(0, 17)
+#define LOONGSON1_PWM1_IRQ LOONGSON1_IRQ(0, 18)
+#define LOONGSON1_PWM2_IRQ LOONGSON1_IRQ(0, 19)
+#define LOONGSON1_PWM3_IRQ LOONGSON1_IRQ(0, 20)
+#define LOONGSON1_RTC_INT0_IRQ LOONGSON1_IRQ(0, 21)
+#define LOONGSON1_RTC_INT1_IRQ LOONGSON1_IRQ(0, 22)
+#define LOONGSON1_RTC_INT2_IRQ LOONGSON1_IRQ(0, 23)
+#define LOONGSON1_TOY_INT0_IRQ LOONGSON1_IRQ(0, 24)
+#define LOONGSON1_TOY_INT1_IRQ LOONGSON1_IRQ(0, 25)
+#define LOONGSON1_TOY_INT2_IRQ LOONGSON1_IRQ(0, 26)
+#define LOONGSON1_RTC_TICK_IRQ LOONGSON1_IRQ(0, 27)
+#define LOONGSON1_TOY_TICK_IRQ LOONGSON1_IRQ(0, 28)
+#define LOONGSON1_UART4_IRQ LOONGSON1_IRQ(0, 29)
+#define LOONGSON1_UART5_IRQ LOONGSON1_IRQ(0, 30)
+
+#define LOONGSON1_OHCI_IRQ LOONGSON1_IRQ(1, 0)
+#define LOONGSON1_EHCI_IRQ LOONGSON1_IRQ(1, 1)
+#define LOONGSON1_GMAC0_IRQ LOONGSON1_IRQ(1, 2)
+#define LOONGSON1_GMAC1_IRQ LOONGSON1_IRQ(1, 3)
+
+#define NR_IRQS LOONGSON1_GMAC1_IRQ
+
+#endif /* __ASM_MACH_LOONGSON1_IRQ_H */
diff --git a/arch/mips/include/asm/mach-loongson1/loongson1.h b/arch/mips/include/asm/mach-loongson1/loongson1.h
new file mode 100644
index 0000000..7aec900
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/loongson1.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Register mappings for Loongson1.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+
+#ifndef __ASM_MACH_LOONGSON1_LOONGSON1_H
+#define __ASM_MACH_LOONGSON1_LOONGSON1_H
+
+#define DEFAULT_MEMSIZE (256) /* If no memsize provided */
+
+/* Loongson1 Register Bases */
+/* All regs are accessed in KSEG1 */
+
+#define LOONGSON1_INTC_BASE (0xbfd01040)
+#define LOONGSON1_USB_BASE (0xbfe00000)
+#define LOONGSON1_GMAC0_BASE (0xbfe10000)
+#define LOONGSON1_GMAC1_BASE (0xbfe20000)
+#define LOONGSON1_UART0_BASE (0xbfe40000)
+#define LOONGSON1_UART1_BASE (0xbfe44000)
+#define LOONGSON1_UART2_BASE (0xbfe48000)
+#define LOONGSON1_UART3_BASE (0xbfe4c000)
+#define LOONGSON1_UART4_BASE (0xbfe6c000)
+#define LOONGSON1_UART5_BASE (0xbfe7c000)
+#define LOONGSON1_CAN0_BASE (0xbfe50000)
+#define LOONGSON1_CAN1_BASE (0xbfe54000)
+#define LOONGSON1_I2C0_BASE (0xbfe58000)
+#define LOONGSON1_I2C1_BASE (0xbfe68000)
+#define LOONGSON1_I2C2_BASE (0xbfe70000)
+#define LOONGSON1_PWM_BASE (0xbfe5c000)
+#define LOONGSON1_WDT_BASE (0xbfe5c060)
+#define LOONGSON1_RTC_BASE (0xbfe64000)
+#define LOONGSON1_AC97_BASE (0xbfe74000)
+#define LOONGSON1_NAND_BASE (0xbfe78000)
+#define LOONGSON1_CLK_BASE (0xbfe78030)
+
+#include <regs-clk.h>
+#include <regs-intc.h>
+#include <regs-wdt.h>
+
+#endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */
diff --git a/arch/mips/include/asm/mach-loongson1/platform.h b/arch/mips/include/asm/mach-loongson1/platform.h
new file mode 100644
index 0000000..db4f02e
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/platform.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+
+#ifndef __ASM_MACH_LOONGSON1_PLATFORM_H
+#define __ASM_MACH_LOONGSON1_PLATFORM_H
+
+#include <linux/platform_device.h>
+
+extern struct platform_device loongson1_uart_device;
+
+void loongson1_serial_setup(void);
+
+#endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */
diff --git a/arch/mips/include/asm/mach-loongson1/prom.h b/arch/mips/include/asm/mach-loongson1/prom.h
new file mode 100644
index 0000000..b871dc4
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/prom.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON1_PROM_H
+#define __ASM_MACH_LOONGSON1_PROM_H
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+/* environment arguments from bootloader */
+extern unsigned long memsize, highmemsize;
+
+/* loongson-specific command line, env and memory initialization */
+extern char *prom_getenv(char *name);
+extern void __init prom_init_cmdline(void);
+
+#endif /* __ASM_MACH_LOONGSON1_PROM_H */
diff --git a/arch/mips/include/asm/mach-loongson1/regs-clk.h b/arch/mips/include/asm/mach-loongson1/regs-clk.h
new file mode 100644
index 0000000..9ea952e
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/regs-clk.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson1 Clock Register Definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON1_REGS_CLK_H
+#define __ASM_MACH_LOONGSON1_REGS_CLK_H
+
+#define LS1_CLK_REG(x) ((void __iomem *)(LOONGSON1_CLK_BASE + (x)))
+
+#define LS1_CLK_PLL_FREQ LS1_CLK_REG(0x0)
+#define LS1_CLK_PLL_DIV LS1_CLK_REG(0x4)
+
+/* Clock PLL Divisor Register Bits */
+#define DIV_DC_EN (0x1 << 31)
+#define DIV_DC (0x1f << 26)
+#define DIV_CPU_EN (0x1 << 25)
+#define DIV_CPU (0x1f << 20)
+#define DIV_DDR_EN (0x1 << 19)
+#define DIV_DDR (0x1f << 14)
+
+#define DIV_DC_SHIFT 26
+#define DIV_CPU_SHIFT 20
+#define DIV_DDR_SHIFT 14
+
+#endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */
diff --git a/arch/mips/include/asm/mach-loongson1/regs-intc.h b/arch/mips/include/asm/mach-loongson1/regs-intc.h
new file mode 100644
index 0000000..c583dcc
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/regs-intc.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson1 Interrupt register definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON1_REGS_INTC_H
+#define __ASM_MACH_LOONGSON1_REGS_INTC_H
+
+#define LS1_INTC_REG(x) \
+ ((void __iomem *)(LOONGSON1_INTC_BASE + (n * 0x18) + x))
+
+#define LS1_INTC_INTISR(n) LS1_INTC_REG(0x0)
+#define LS1_INTC_INTIEN(n) LS1_INTC_REG(0x4)
+#define LS1_INTC_INTSET(n) LS1_INTC_REG(0x8)
+#define LS1_INTC_INTCLR(n) LS1_INTC_REG(0xc)
+#define LS1_INTC_INTPOL(n) LS1_INTC_REG(0x10)
+#define LS1_INTC_INTEDGE(n) LS1_INTC_REG(0x14)
+
+#endif /* __ASM_MACH_LOONGSON1_REGS_INTC_H */
diff --git a/arch/mips/include/asm/mach-loongson1/regs-wdt.h b/arch/mips/include/asm/mach-loongson1/regs-wdt.h
new file mode 100644
index 0000000..aee47aa
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/regs-wdt.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson1 Watchdog register definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON1_REGS_WDT_H
+#define __ASM_MACH_LOONGSON1_REGS_WDT_H
+
+#define LS1_WDT_REG(x) ((void __iomem *)(LOONGSON1_WDT_BASE + (x)))
+
+#define LS1_WDT_EN LS1_WDT_REG(0x0)
+#define LS1_WDT_SET LS1_WDT_REG(0x4)
+#define LS1_WDT_TIMER LS1_WDT_REG(0x8)
+
+#endif /* __ASM_MACH_LOONGSON1_REGS_WDT_H */
diff --git a/arch/mips/include/asm/mach-loongson1/war.h b/arch/mips/include/asm/mach-loongson1/war.h
new file mode 100644
index 0000000..e3680a8
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/war.h
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MACH_LOONGSON1_WAR_H
+#define __ASM_MACH_LOONGSON1_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR 0
+#define R4600_V1_HIT_CACHEOP_WAR 0
+#define R4600_V2_HIT_CACHEOP_WAR 0
+#define R5432_CP0_INTERRUPT_WAR 0
+#define BCM1250_M3_WAR 0
+#define SIBYTE_1956_WAR 0
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
+#define TX49XX_ICACHE_INDEX_INV_WAR 0
+#define RM9000_CDEX_SMP_WAR 0
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
+#define R10000_LLSC_WAR 0
+#define MIPS34K_MISSED_ITLB_WAR 0
+
+#endif /* __ASM_MACH_LOONGSON1_WAR_H */
diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
index bc01a02..b53d642 100644
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -116,6 +116,8 @@ search_module_dbetables(unsigned long addr)
#define MODULE_PROC_FAMILY "SB1 "
#elif defined CONFIG_CPU_LOONGSON2
#define MODULE_PROC_FAMILY "LOONGSON2 "
+#elif defined CONFIG_CPU_LOONGSON1
+#define MODULE_PROC_FAMILY "LOONGSON1 "
#elif defined CONFIG_CPU_CAVIUM_OCTEON
#define MODULE_PROC_FAMILY "OCTEON "
#elif defined CONFIG_CPU_XLR
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 664bc13..98d4235 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -37,6 +37,8 @@
void (*cpu_wait)(void);
EXPORT_SYMBOL(cpu_wait);
+static void __cpuinit decode_configs(struct cpuinfo_mips *c);
+
static void r3081_wait(void)
{
unsigned long cfg = read_c0_conf();
@@ -191,6 +193,7 @@ void __init check_wait(void)
case CPU_CAVIUM_OCTEON2:
case CPU_JZRISC:
case CPU_XLR:
+ case CPU_LOONGSON1:
cpu_wait = r4k_wait;
break;
@@ -636,6 +639,18 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
MIPS_CPU_32FPR;
c->tlbsize = 64;
break;
+ case PRID_IMP_LOONGSON1:
+ decode_configs(c);
+
+ c->cputype = CPU_LOONGSON1;
+
+ switch (c->processor_id & PRID_REV_MASK) {
+ case PRID_REV_LOONGSON1B:
+ __cpu_name[cpu] = "Loongson 1B";
+ break;
+ }
+
+ break;
}
}
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index e5ad09a..e316b0e 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1062,6 +1062,12 @@ init_hw_perf_events(void)
mipsxxcore_pmu.irq = irq;
mipspmu = &mipsxxcore_pmu;
break;
+ case CPU_LOONGSON1:
+ mipsxxcore_pmu.name = "mips/loongson1";
+ mipsxxcore_pmu.num_counters = counters;
+ mipsxxcore_pmu.irq = irq;
+ mipspmu = &mipsxxcore_pmu;
+ break;
default:
pr_cont("Either hardware does not support performance "
"counters, or not yet implemented.\n");
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 01eff7e..cd55823 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1241,6 +1241,7 @@ static inline void parity_protection_init(void)
break;
case CPU_5KC:
+ case CPU_LOONGSON1:
write_c0_ecc(0x80000000);
back_to_back_c0_hazard();
/* Set the PE bit (bit 31) in the c0_errctl register. */
diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson1/Kconfig
new file mode 100644
index 0000000..237fa21
--- /dev/null
+++ b/arch/mips/loongson1/Kconfig
@@ -0,0 +1,21 @@
+if MACH_LOONGSON1
+
+choice
+ prompt "Machine Type"
+
+config LOONGSON1_LS1B
+ bool "Loongson LS1B board"
+ select CEVT_R4K
+ select CSRC_R4K
+ select SYS_HAS_CPU_LOONGSON1B
+ select DMA_NONCOHERENT
+ select BOOT_ELF32
+ select IRQ_CPU
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_HIGHMEM
+ select SYS_HAS_EARLY_PRINTK
+
+endchoice
+
+endif # MACH_LOONGSON1
diff --git a/arch/mips/loongson1/Makefile b/arch/mips/loongson1/Makefile
new file mode 100644
index 0000000..e9123c2
--- /dev/null
+++ b/arch/mips/loongson1/Makefile
@@ -0,0 +1,11 @@
+#
+# Common code for all Loongson1 based systems
+#
+
+obj-$(CONFIG_MACH_LOONGSON1) += common/
+
+#
+# Loongson LS1B board
+#
+
+obj-$(CONFIG_LOONGSON1_LS1B) += ls1b/
diff --git a/arch/mips/loongson1/Platform b/arch/mips/loongson1/Platform
new file mode 100644
index 0000000..92804c6
--- /dev/null
+++ b/arch/mips/loongson1/Platform
@@ -0,0 +1,7 @@
+cflags-$(CONFIG_CPU_LOONGSON1) += \
+ $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
+ -Wa,-mips32r2 -Wa,--trap
+
+platform-$(CONFIG_MACH_LOONGSON1) += loongson1/
+cflags-$(CONFIG_MACH_LOONGSON1) += -I$(srctree)/arch/mips/include/asm/mach-loongson1
+load-$(CONFIG_LOONGSON1_LS1B) += 0xffffffff80010000
diff --git a/arch/mips/loongson1/common/Makefile b/arch/mips/loongson1/common/Makefile
new file mode 100644
index 0000000..b279770
--- /dev/null
+++ b/arch/mips/loongson1/common/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for common code of loongson1 based machines.
+#
+
+obj-y += clock.o irq.o platform.o prom.o reset.o setup.o
diff --git a/arch/mips/loongson1/common/clock.c b/arch/mips/loongson1/common/clock.c
new file mode 100644
index 0000000..7f4f28b
--- /dev/null
+++ b/arch/mips/loongson1/common/clock.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <asm/clock.h>
+#include <asm/time.h>
+
+#include <loongson1.h>
+
+static LIST_HEAD(clocks);
+static DEFINE_MUTEX(clocks_mutex);
+
+struct clk *clk_get(struct device *dev, const char *name)
+{
+ struct clk *c;
+ struct clk *ret = NULL;
+
+ mutex_lock(&clocks_mutex);
+ list_for_each_entry(c, &clocks, node) {
+ if (!strcmp(c->name, name)) {
+ ret = c;
+ break;
+ }
+ }
+ mutex_unlock(&clocks_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_get);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+static void pll_clk_init(struct clk *clk)
+{
+ u32 pll;
+
+ pll = __raw_readl(LS1_CLK_PLL_FREQ);
+ clk->rate = (12 + (pll & 0x3f)) * 33 / 2
+ + ((pll >> 8) & 0x3ff) * 33 / 1024 / 2;
+ clk->rate *= 1000000;
+}
+
+static void cpu_clk_init(struct clk *clk)
+{
+ u32 pll, ctrl;
+
+ pll = clk_get_rate(clk->parent);
+ ctrl = __raw_readl(LS1_CLK_PLL_DIV) & DIV_CPU;
+ clk->rate = pll / (ctrl >> DIV_CPU_SHIFT);
+}
+
+static void ddr_clk_init(struct clk *clk)
+{
+ u32 pll, ctrl;
+
+ pll = clk_get_rate(clk->parent);
+ ctrl = __raw_readl(LS1_CLK_PLL_DIV) & DIV_DDR;
+ clk->rate = pll / (ctrl >> DIV_DDR_SHIFT);
+}
+
+static void dc_clk_init(struct clk *clk)
+{
+ u32 pll, ctrl;
+
+ pll = clk_get_rate(clk->parent);
+ ctrl = __raw_readl(LS1_CLK_PLL_DIV) & DIV_DC;
+ clk->rate = pll / (ctrl >> DIV_DC_SHIFT);
+}
+
+static struct clk_ops pll_clk_ops = {
+ .init = pll_clk_init,
+};
+
+static struct clk_ops cpu_clk_ops = {
+ .init = cpu_clk_init,
+};
+
+static struct clk_ops ddr_clk_ops = {
+ .init = ddr_clk_init,
+};
+
+static struct clk_ops dc_clk_ops = {
+ .init = dc_clk_init,
+};
+
+static struct clk pll_clk = {
+ .name = "pll",
+ .ops = &pll_clk_ops,
+};
+
+static struct clk cpu_clk = {
+ .name = "cpu",
+ .parent = &pll_clk,
+ .ops = &cpu_clk_ops,
+};
+
+static struct clk ddr_clk = {
+ .name = "ddr",
+ .parent = &pll_clk,
+ .ops = &ddr_clk_ops,
+};
+
+static struct clk dc_clk = {
+ .name = "dc",
+ .parent = &pll_clk,
+ .ops = &dc_clk_ops,
+};
+
+int clk_register(struct clk *clk)
+{
+ mutex_lock(&clocks_mutex);
+ list_add(&clk->node, &clocks);
+ if (clk->ops->init)
+ clk->ops->init(clk);
+ mutex_unlock(&clocks_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+static struct clk *loongson1_clks[] = {
+ &pll_clk,
+ &cpu_clk,
+ &ddr_clk,
+ &dc_clk,
+};
+
+int __init loongson1_clock_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(loongson1_clks); i++)
+ clk_register(loongson1_clks[i]);
+
+ return 0;
+}
+
+void __init plat_time_init(void)
+{
+ struct clk *clk;
+
+ /* Initialize loongson1 clocks */
+ loongson1_clock_init();
+
+ /* setup mips r4k timer */
+ clk = clk_get(NULL, "cpu");
+ if (IS_ERR(clk))
+ panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
+
+ mips_hpt_frequency = clk_get_rate(clk) / 2;
+}
diff --git a/arch/mips/loongson1/common/irq.c b/arch/mips/loongson1/common/irq.c
new file mode 100644
index 0000000..a5dcabb
--- /dev/null
+++ b/arch/mips/loongson1/common/irq.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/irq_cpu.h>
+
+#include <loongson1.h>
+#include <irq.h>
+
+static void loongson1_irq_ack(struct irq_data *d)
+{
+ unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
+ unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
+
+ __raw_writel(__raw_readl(LS1_INTC_INTCLR(n))
+ | (1 << bit), LS1_INTC_INTCLR(n));
+}
+
+static void loongson1_irq_mask(struct irq_data *d)
+{
+ unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
+ unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
+
+ __raw_writel(__raw_readl(LS1_INTC_INTIEN(n))
+ & ~(1 << bit), LS1_INTC_INTIEN(n));
+}
+
+static void loongson1_irq_mask_ack(struct irq_data *d)
+{
+ unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
+ unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
+
+ __raw_writel(__raw_readl(LS1_INTC_INTIEN(n))
+ & ~(1 << bit), LS1_INTC_INTIEN(n));
+ __raw_writel(__raw_readl(LS1_INTC_INTCLR(n))
+ | (1 << bit), LS1_INTC_INTCLR(n));
+}
+
+static void loongson1_irq_unmask(struct irq_data *d)
+{
+ unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
+ unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
+
+ __raw_writel(__raw_readl(LS1_INTC_INTIEN(n))
+ | (1 << bit), LS1_INTC_INTIEN(n));
+}
+
+static struct irq_chip loongson1_irq_chip = {
+ .name = "LOONGSON1-INTC",
+ .irq_ack = loongson1_irq_ack,
+ .irq_mask = loongson1_irq_mask,
+ .irq_mask_ack = loongson1_irq_mask_ack,
+ .irq_unmask = loongson1_irq_unmask,
+};
+
+static void loongson1_irq_dispatch(int n)
+{
+ u32 int_status, irq;
+
+ /* Get pending sources, masked by current enables */
+ int_status = __raw_readl(LS1_INTC_INTISR(n)) &
+ __raw_readl(LS1_INTC_INTIEN(n));
+
+ if (int_status) {
+ irq = LOONGSON1_IRQ(n, __ffs(int_status));
+ do_IRQ(irq);
+ }
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending;
+
+ pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (pending & CAUSEF_IP7)
+ do_IRQ(TIMER_IRQ);
+ else if (pending & CAUSEF_IP2)
+ loongson1_irq_dispatch(0); /* INT0 */
+ else if (pending & CAUSEF_IP3)
+ loongson1_irq_dispatch(1); /* INT1 */
+ else if (pending & CAUSEF_IP4)
+ loongson1_irq_dispatch(2); /* INT2 */
+ else if (pending & CAUSEF_IP5)
+ loongson1_irq_dispatch(3); /* INT3 */
+ else if (pending & CAUSEF_IP6)
+ loongson1_irq_dispatch(4); /* INT4 */
+ else
+ spurious_interrupt();
+
+}
+
+struct irqaction cascade_irqaction = {
+ .handler = no_action,
+ .name = "cascade",
+ .flags = IRQF_NO_THREAD,
+};
+
+static void __init loongson1_irq_init(int base)
+{
+ int n;
+
+ /* Disable interrupts and clear pending,
+ * setup all IRQs as high level triggered
+ */
+ for (n = 0; n < 4; n++) {
+ __raw_writel(0x0, LS1_INTC_INTIEN(n));
+ __raw_writel(0xffffffff, LS1_INTC_INTCLR(n));
+ __raw_writel(0xffffffff, LS1_INTC_INTPOL(n));
+ __raw_writel(0x0, LS1_INTC_INTEDGE(n));
+ }
+
+
+ for (n = base; n < NR_IRQS; n++) {
+ irq_set_chip_and_handler(n, &loongson1_irq_chip,
+ handle_level_irq);
+ }
+
+ setup_irq(INT0_IRQ, &cascade_irqaction);
+ setup_irq(INT1_IRQ, &cascade_irqaction);
+ setup_irq(INT2_IRQ, &cascade_irqaction);
+ setup_irq(INT3_IRQ, &cascade_irqaction);
+}
+
+void __init arch_init_irq(void)
+{
+ mips_cpu_irq_init();
+ loongson1_irq_init(LOONGSON1_IRQ_BASE);
+}
diff --git a/arch/mips/loongson1/common/platform.c b/arch/mips/loongson1/common/platform.c
new file mode 100644
index 0000000..c93028e
--- /dev/null
+++ b/arch/mips/loongson1/common/platform.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/serial_8250.h>
+
+#include <loongson1.h>
+
+#define LOONGSON1_UART_PORT(_id) \
+ { \
+ .mapbase = LOONGSON1_UART ## _id ## _BASE, \
+ .membase = (void *)(LOONGSON1_UART ## _id ## _BASE), \
+ .irq = LOONGSON1_UART ## _id ## _IRQ, \
+ .iotype = UPIO_MEM, \
+ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, \
+ .type = PORT_16550A, \
+ }
+
+static struct plat_serial8250_port loongson1_serial8250_port[] = {
+ LOONGSON1_UART_PORT(0),
+ {},
+};
+
+struct platform_device loongson1_uart_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = loongson1_serial8250_port,
+ },
+};
+
+void __init loongson1_serial_setup(void)
+{
+ struct clk *clk;
+ struct plat_serial8250_port *p;
+
+ clk = clk_get(NULL, "dc");
+ if (IS_ERR(clk))
+ panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
+
+ for (p = loongson1_serial8250_port; p->flags != 0; ++p)
+ p->uartclk = clk_get_rate(clk);
+}
diff --git a/arch/mips/loongson1/common/prom.c b/arch/mips/loongson1/common/prom.c
new file mode 100644
index 0000000..70791f1
--- /dev/null
+++ b/arch/mips/loongson1/common/prom.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Modified from arch/mips/pnx833x/common/prom.c.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/serial_reg.h>
+#include <asm/bootinfo.h>
+
+#include <loongson1.h>
+#include <prom.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+unsigned long memsize, highmemsize;
+
+char *prom_getenv(char *envname)
+{
+ char **env = prom_envp;
+ int i;
+
+ i = strlen(envname);
+
+ while (*env) {
+ if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=')
+ return *env + i + 1;
+ env++;
+ }
+
+ return 0;
+}
+
+static inline unsigned long env_or_default(char *env, unsigned long dfl)
+{
+ char *str = prom_getenv(env);
+ return str ? simple_strtol(str, 0, 0) : dfl;
+}
+
+void __init prom_init_cmdline(void)
+{
+ char *c = &(arcs_cmdline[0]);
+ int i;
+
+ for (i = 1; i < prom_argc; i++) {
+ strcpy(c, prom_argv[i]);
+ c += strlen(prom_argv[i]);
+ if (i < prom_argc-1)
+ *c++ = ' ';
+ }
+ *c = 0;
+}
+
+void __init prom_init(void)
+{
+ prom_argc = fw_arg0;
+ prom_argv = (char **)fw_arg1;
+ prom_envp = (char **)fw_arg2;
+
+ prom_init_cmdline();
+
+ memsize = env_or_default("memsize", DEFAULT_MEMSIZE);
+ highmemsize = env_or_default("highmemsize", 0x0);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+#define UART_BASE LOONGSON1_UART0_BASE
+#define PORT(base, offset) (u8 *)(base + offset)
+
+void __init prom_putchar(char c)
+{
+ int timeout;
+
+ timeout = 1024;
+
+ while (((readb(PORT(UART_BASE, UART_LSR)) & UART_LSR_THRE) == 0)
+ && (timeout-- > 0))
+ ;
+
+ writeb(c, PORT(UART_BASE, UART_TX));
+}
diff --git a/arch/mips/loongson1/common/reset.c b/arch/mips/loongson1/common/reset.c
new file mode 100644
index 0000000..75f550f
--- /dev/null
+++ b/arch/mips/loongson1/common/reset.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <asm/reboot.h>
+
+#include <loongson1.h>
+
+static void loongson1_restart(char *command)
+{
+ __raw_writel(0x1, LS1_WDT_EN);
+ __raw_writel(0x5000000, LS1_WDT_TIMER);
+ __raw_writel(0x1, LS1_WDT_SET);
+}
+
+static void loongson1_halt(void)
+{
+ pr_notice("\n\n** You can safely turn off the power now **\n\n");
+ while (1) {
+ if (cpu_wait)
+ cpu_wait();
+ }
+}
+
+static void loongson1_power_off(void)
+{
+ loongson1_halt();
+}
+
+static int __init loongson1_reboot_setup(void)
+{
+ _machine_restart = loongson1_restart;
+ _machine_halt = loongson1_halt;
+ pm_power_off = loongson1_power_off;
+
+ return 0;
+}
+
+arch_initcall(loongson1_reboot_setup);
diff --git a/arch/mips/loongson1/common/setup.c b/arch/mips/loongson1/common/setup.c
new file mode 100644
index 0000000..62128cc
--- /dev/null
+++ b/arch/mips/loongson1/common/setup.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/bootinfo.h>
+
+#include <prom.h>
+
+void __init plat_mem_setup(void)
+{
+ add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
+}
+
+const char *get_system_type(void)
+{
+ unsigned int processor_id = (¤t_cpu_data)->processor_id;
+
+ switch (processor_id & PRID_REV_MASK) {
+ case PRID_REV_LOONGSON1B:
+ return "LOONGSON LS1B";
+ default:
+ return "LOONGSON (unknown)";
+ }
+}
diff --git a/arch/mips/loongson1/ls1b/Makefile b/arch/mips/loongson1/ls1b/Makefile
new file mode 100644
index 0000000..891eac4
--- /dev/null
+++ b/arch/mips/loongson1/ls1b/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for loongson1B based machines.
+#
+
+obj-y += board.o
diff --git a/arch/mips/loongson1/ls1b/board.c b/arch/mips/loongson1/ls1b/board.c
new file mode 100644
index 0000000..b1a602f
--- /dev/null
+++ b/arch/mips/loongson1/ls1b/board.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <platform.h>
+
+#include <linux/serial_8250.h>
+#include <loongson1.h>
+
+static struct platform_device *loongson1_platform_devices[] __initdata = {
+ &loongson1_uart_device,
+};
+
+static int __init loongson1_platform_init(void)
+{
+ int err;
+
+ loongson1_serial_setup();
+
+ err = platform_add_devices(loongson1_platform_devices,
+ ARRAY_SIZE(loongson1_platform_devices));
+ return err;
+}
+
+arch_initcall(loongson1_platform_init);
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index d1f2d4c..99216f0 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -89,6 +89,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
case CPU_R10000:
case CPU_R12000:
case CPU_R14000:
+ case CPU_LOONGSON1:
lmodel = &op_model_mipsxx_ops;
break;
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 54759f1..03be670 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -365,6 +365,10 @@ static int __init mipsxx_init(void)
op_model_mipsxx_ops.cpu_type = "mips/sb1";
break;
+ case CPU_LOONGSON1:
+ op_model_mipsxx_ops.cpu_type = "mips/loongson1";
+ break;
+
default:
printk(KERN_ERR "Profiling unsupported for this CPU\n");
--
1.7.1
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 2/2] MIPS: Add defconfig for Loongson1B (UPDATED)
2011-09-26 9:37 [PATCH 1/2] MIPS: Add basic support for Loongson1B (UPDATED) keguang.zhang
@ 2011-09-26 9:37 ` keguang.zhang
0 siblings, 0 replies; 8+ messages in thread
From: keguang.zhang @ 2011-09-26 9:37 UTC (permalink / raw)
To: linux-mips, linux-kernel; +Cc: ralf, wuzhangjin, r0bertz, chenj, Kelvin Cheung
From: Kelvin Cheung <keguang.zhang@gmail.com>
This patch adds defconfig for Loongson1B.
Signed-off-by: Kelvin Cheung <keguang.zhang@gmail.com>
---
arch/mips/configs/ls1b_defconfig | 86 ++++++++++++++++++++++++++++++++++++++
1 files changed, 86 insertions(+), 0 deletions(-)
create mode 100644 arch/mips/configs/ls1b_defconfig
diff --git a/arch/mips/configs/ls1b_defconfig b/arch/mips/configs/ls1b_defconfig
new file mode 100644
index 0000000..b4e67ee
--- /dev/null
+++ b/arch/mips/configs/ls1b_defconfig
@@ -0,0 +1,86 @@
+CONFIG_MACH_LOONGSON1=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+# CONFIG_SECCOMP is not set
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TINY_RCU=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_EXPERT=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_LEGACY_PTY_COUNT=8
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+# CONFIG_HW_RANDOM is not set
+CONFIG_RAMOOPS=y
+# CONFIG_HWMON is not set
+# CONFIG_MFD_SUPPORT is not set
+# CONFIG_VGA_CONSOLE is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_MISC_FILESYSTEMS is not set
+# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_FTRACE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_CRC32 is not set
--
1.7.1
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] MIPS: Add basic support for Loongson1B (UPDATED)
@ 2011-09-24 6:21 keguang.zhang
2011-09-25 5:27 ` wu zhangjin
0 siblings, 1 reply; 8+ messages in thread
From: keguang.zhang @ 2011-09-24 6:21 UTC (permalink / raw)
To: linux-mips, linux-kernel; +Cc: ralf, wuzhangjin, r0bertz, chenj, Kelvin Cheung
From: Kelvin Cheung <keguang.zhang@gmail.com>
This patch adds basic support for Loongson1B
including serial port, timer and interrupt handler.
Loongson 1B is a 32-bit SoC designed by Institute of
Computing Technology (ICT), Chinese Academy of Sciences (CAS),
which implements the MIPS32 release 2 instruction set.
Signed-off-by: Kelvin Cheung <keguang.zhang@gmail.com>
---
arch/mips/Kbuild.platforms | 1 +
arch/mips/Kconfig | 31 ++++
arch/mips/include/asm/cpu.h | 3 +-
arch/mips/include/asm/mach-loongson1/irq.h | 70 +++++++++
arch/mips/include/asm/mach-loongson1/loongson1.h | 48 +++++++
arch/mips/include/asm/mach-loongson1/platform.h | 20 +++
arch/mips/include/asm/mach-loongson1/prom.h | 24 +++
arch/mips/include/asm/mach-loongson1/regs-clk.h | 32 ++++
arch/mips/include/asm/mach-loongson1/regs-intc.h | 25 ++++
arch/mips/include/asm/mach-loongson1/regs-wdt.h | 21 +++
arch/mips/include/asm/mach-loongson1/war.h | 25 ++++
arch/mips/include/asm/module.h | 2 +
arch/mips/kernel/cpu-probe.c | 15 ++
arch/mips/kernel/perf_event_mipsxx.c | 6 +
arch/mips/kernel/traps.c | 1 +
arch/mips/loongson1/Kconfig | 21 +++
arch/mips/loongson1/Makefile | 11 ++
arch/mips/loongson1/Platform | 7 +
arch/mips/loongson1/common/Makefile | 5 +
arch/mips/loongson1/common/clock.c | 165 ++++++++++++++++++++++
arch/mips/loongson1/common/irq.c | 136 ++++++++++++++++++
arch/mips/loongson1/common/platform.c | 50 +++++++
arch/mips/loongson1/common/prom.c | 88 ++++++++++++
arch/mips/loongson1/common/reset.c | 46 ++++++
arch/mips/loongson1/common/setup.c | 29 ++++
arch/mips/loongson1/ls1b/Makefile | 5 +
arch/mips/loongson1/ls1b/board.c | 30 ++++
arch/mips/oprofile/common.c | 1 +
arch/mips/oprofile/op_model_mipsxx.c | 4 +
29 files changed, 921 insertions(+), 1 deletions(-)
create mode 100644 arch/mips/include/asm/mach-loongson1/irq.h
create mode 100644 arch/mips/include/asm/mach-loongson1/loongson1.h
create mode 100644 arch/mips/include/asm/mach-loongson1/platform.h
create mode 100644 arch/mips/include/asm/mach-loongson1/prom.h
create mode 100644 arch/mips/include/asm/mach-loongson1/regs-clk.h
create mode 100644 arch/mips/include/asm/mach-loongson1/regs-intc.h
create mode 100644 arch/mips/include/asm/mach-loongson1/regs-wdt.h
create mode 100644 arch/mips/include/asm/mach-loongson1/war.h
create mode 100644 arch/mips/loongson1/Kconfig
create mode 100644 arch/mips/loongson1/Makefile
create mode 100644 arch/mips/loongson1/Platform
create mode 100644 arch/mips/loongson1/common/Makefile
create mode 100644 arch/mips/loongson1/common/clock.c
create mode 100644 arch/mips/loongson1/common/irq.c
create mode 100644 arch/mips/loongson1/common/platform.c
create mode 100644 arch/mips/loongson1/common/prom.c
create mode 100644 arch/mips/loongson1/common/reset.c
create mode 100644 arch/mips/loongson1/common/setup.c
create mode 100644 arch/mips/loongson1/ls1b/Makefile
create mode 100644 arch/mips/loongson1/ls1b/board.c
diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
index 5ce8029..d64786d 100644
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -14,6 +14,7 @@ platforms += jz4740
platforms += lantiq
platforms += lasat
platforms += loongson
+platforms += loongson1
platforms += mipssim
platforms += mti-malta
platforms += netlogic
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index d9b8ea8..4c6ad4f 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -262,6 +262,17 @@ config MACH_LOONGSON
Chinese Academy of Sciences (CAS) in the People's Republic
of China. The chief architect is Professor Weiwu Hu.
+config MACH_LOONGSON1
+ bool "Loongson1 family of machines"
+ select SYS_SUPPORTS_ZBOOT
+ help
+ This enables the support of Loongson1 family of machines.
+
+ Loongson1 is a family of 32-bit MIPS-compatible SoCs.
+ developed at Institute of Computing Technology (ICT),
+ Chinese Academy of Sciences (CAS) in the People's Republic
+ of China.
+
config MIPS_MALTA
bool "MIPS Malta board"
select ARCH_MAY_HAVE_PC_FDC
@@ -808,6 +819,7 @@ source "arch/mips/txx9/Kconfig"
source "arch/mips/vr41xx/Kconfig"
source "arch/mips/cavium-octeon/Kconfig"
source "arch/mips/loongson/Kconfig"
+source "arch/mips/loongson1/Kconfig"
source "arch/mips/netlogic/Kconfig"
endmenu
@@ -1201,6 +1213,14 @@ config CPU_LOONGSON2F
have a similar programming interface with FPGA northbridge used in
Loongson2E.
+config CPU_LOONGSON1B
+ bool "Loongson 1B"
+ depends on SYS_HAS_CPU_LOONGSON1B
+ select CPU_LOONGSON1
+ help
+ The Loongson 1B is a 32-bit SoC, which implements the MIPS32
+ release 2 instruction set.
+
config CPU_MIPS32_R1
bool "MIPS32 Release 1"
depends on SYS_HAS_CPU_MIPS32_R1
@@ -1529,6 +1549,14 @@ config CPU_LOONGSON2
select CPU_SUPPORTS_64BIT_KERNEL
select CPU_SUPPORTS_HIGHMEM
+config CPU_LOONGSON1
+ bool
+ select CPU_MIPS32
+ select CPU_MIPSR2
+ select CPU_HAS_PREFETCH
+ select CPU_SUPPORTS_32BIT_KERNEL
+ select CPU_SUPPORTS_HIGHMEM
+
config SYS_HAS_CPU_LOONGSON2E
bool
@@ -1538,6 +1566,9 @@ config SYS_HAS_CPU_LOONGSON2F
select CPU_SUPPORTS_ADDRWINCFG if 64BIT
select CPU_SUPPORTS_UNCACHED_ACCELERATED
+config SYS_HAS_CPU_LOONGSON1B
+ bool
+
config SYS_HAS_CPU_MIPS32_R1
bool
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 5f95a4b..975f372 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -191,6 +191,7 @@
#define PRID_REV_34K_V1_0_2 0x0022
#define PRID_REV_LOONGSON2E 0x0002
#define PRID_REV_LOONGSON2F 0x0003
+#define PRID_REV_LOONGSON1B 0x0020
/*
* Older processors used to encode processor version and revision in two
@@ -253,7 +254,7 @@ enum cpu_type_enum {
*/
CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
- CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC,
+ CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1,
/*
* MIPS64 class processors
diff --git a/arch/mips/include/asm/mach-loongson1/irq.h b/arch/mips/include/asm/mach-loongson1/irq.h
new file mode 100644
index 0000000..e8fed7a
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/irq.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * IRQ mappings for Loongson1.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+
+#ifndef __ASM_MACH_LOONGSON1_IRQ_H
+#define __ASM_MACH_LOONGSON1_IRQ_H
+
+/*
+ * CPU core Interrupt Numbers
+ */
+#define MIPS_CPU_IRQ_BASE 0
+#define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x))
+#define SOFTINT0_IRQ MIPS_CPU_IRQ(0)
+#define SOFTINT1_IRQ MIPS_CPU_IRQ(1)
+#define INT0_IRQ MIPS_CPU_IRQ(2)
+#define INT1_IRQ MIPS_CPU_IRQ(3)
+#define INT2_IRQ MIPS_CPU_IRQ(4)
+#define INT3_IRQ MIPS_CPU_IRQ(5)
+#define INT4_IRQ MIPS_CPU_IRQ(6)
+#define TIMER_IRQ MIPS_CPU_IRQ(7) /* cpu timer */
+
+/*
+ * INT0~3 Interrupt Numbers
+ */
+#define LOONGSON1_IRQ_BASE 8
+#define LOONGSON1_IRQ(n, x) (LOONGSON1_IRQ_BASE + (n << 5) + (x))
+
+#define LOONGSON1_UART0_IRQ LOONGSON1_IRQ(0, 2)
+#define LOONGSON1_UART1_IRQ LOONGSON1_IRQ(0, 3)
+#define LOONGSON1_UART2_IRQ LOONGSON1_IRQ(0, 4)
+#define LOONGSON1_UART3_IRQ LOONGSON1_IRQ(0, 5)
+#define LOONGSON1_CAN0_IRQ LOONGSON1_IRQ(0, 6)
+#define LOONGSON1_CAN1_IRQ LOONGSON1_IRQ(0, 7)
+#define LOONGSON1_SPI0_IRQ LOONGSON1_IRQ(0, 8)
+#define LOONGSON1_SPI1_IRQ LOONGSON1_IRQ(0, 9)
+#define LOONGSON1_AC97_IRQ LOONGSON1_IRQ(0, 10)
+#define LOONGSON1_DMA0_IRQ LOONGSON1_IRQ(0, 13)
+#define LOONGSON1_DMA1_IRQ LOONGSON1_IRQ(0, 14)
+#define LOONGSON1_DMA2_IRQ LOONGSON1_IRQ(0, 15)
+#define LOONGSON1_PWM0_IRQ LOONGSON1_IRQ(0, 17)
+#define LOONGSON1_PWM1_IRQ LOONGSON1_IRQ(0, 18)
+#define LOONGSON1_PWM2_IRQ LOONGSON1_IRQ(0, 19)
+#define LOONGSON1_PWM3_IRQ LOONGSON1_IRQ(0, 20)
+#define LOONGSON1_RTC_INT0_IRQ LOONGSON1_IRQ(0, 21)
+#define LOONGSON1_RTC_INT1_IRQ LOONGSON1_IRQ(0, 22)
+#define LOONGSON1_RTC_INT2_IRQ LOONGSON1_IRQ(0, 23)
+#define LOONGSON1_TOY_INT0_IRQ LOONGSON1_IRQ(0, 24)
+#define LOONGSON1_TOY_INT1_IRQ LOONGSON1_IRQ(0, 25)
+#define LOONGSON1_TOY_INT2_IRQ LOONGSON1_IRQ(0, 26)
+#define LOONGSON1_RTC_TICK_IRQ LOONGSON1_IRQ(0, 27)
+#define LOONGSON1_TOY_TICK_IRQ LOONGSON1_IRQ(0, 28)
+#define LOONGSON1_UART4_IRQ LOONGSON1_IRQ(0, 29)
+#define LOONGSON1_UART5_IRQ LOONGSON1_IRQ(0, 30)
+
+#define LOONGSON1_OHCI_IRQ LOONGSON1_IRQ(1, 0)
+#define LOONGSON1_EHCI_IRQ LOONGSON1_IRQ(1, 1)
+#define LOONGSON1_GMAC0_IRQ LOONGSON1_IRQ(1, 2)
+#define LOONGSON1_GMAC1_IRQ LOONGSON1_IRQ(1, 3)
+
+#define NR_IRQS LOONGSON1_GMAC1_IRQ
+
+#endif /* __ASM_MACH_LOONGSON1_IRQ_H */
diff --git a/arch/mips/include/asm/mach-loongson1/loongson1.h b/arch/mips/include/asm/mach-loongson1/loongson1.h
new file mode 100644
index 0000000..466136d
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/loongson1.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Register mappings for Loongson1.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+
+#ifndef __ASM_MACH_LOONGSON1_LOONGSON1_H
+#define __ASM_MACH_LOONGSON1_LOONGSON1_H
+
+#define DEFAULT_MEMSIZE (256) /* If no memsize provided */
+
+/* Loongson1 Register Bases */
+/* All regs are accessed in KSEG1 */
+#define LOONGSON1_REGBASE (0xa0000000ul + 0x1fe00000ul)
+
+#define LOONGSON1_INTC_BASE (0xbfd01040)
+#define LOONGSON1_USB_BASE (0xbfe00000)
+#define LOONGSON1_GMAC0_BASE (0xbfe10000)
+#define LOONGSON1_GMAC1_BASE (0xbfe20000)
+#define LOONGSON1_UART0_BASE (0xbfe40000)
+#define LOONGSON1_UART1_BASE (0xbfe44000)
+#define LOONGSON1_UART2_BASE (0xbfe48000)
+#define LOONGSON1_UART3_BASE (0xbfe4c000)
+#define LOONGSON1_UART4_BASE (0xbfe6c000)
+#define LOONGSON1_UART5_BASE (0xbfe7c000)
+#define LOONGSON1_CAN0_BASE (0xbfe50000)
+#define LOONGSON1_CAN1_BASE (0xbfe54000)
+#define LOONGSON1_I2C0_BASE (0xbfe58000)
+#define LOONGSON1_I2C1_BASE (0xbfe68000)
+#define LOONGSON1_I2C2_BASE (0xbfe70000)
+#define LOONGSON1_PWM_BASE (0xbfe5c000)
+#define LOONGSON1_WDT_BASE (0xbfe5c060)
+#define LOONGSON1_RTC_BASE (0xbfe64000)
+#define LOONGSON1_AC97_BASE (0xbfe74000)
+#define LOONGSON1_NAND_BASE (0xbfe78000)
+#define LOONGSON1_CLK_BASE (0xbfe78030)
+
+#include <regs-clk.h>
+#include <regs-intc.h>
+#include <regs-wdt.h>
+
+#endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */
diff --git a/arch/mips/include/asm/mach-loongson1/platform.h b/arch/mips/include/asm/mach-loongson1/platform.h
new file mode 100644
index 0000000..db4f02e
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/platform.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+
+#ifndef __ASM_MACH_LOONGSON1_PLATFORM_H
+#define __ASM_MACH_LOONGSON1_PLATFORM_H
+
+#include <linux/platform_device.h>
+
+extern struct platform_device loongson1_uart_device;
+
+void loongson1_serial_setup(void);
+
+#endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */
diff --git a/arch/mips/include/asm/mach-loongson1/prom.h b/arch/mips/include/asm/mach-loongson1/prom.h
new file mode 100644
index 0000000..b871dc4
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/prom.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON1_PROM_H
+#define __ASM_MACH_LOONGSON1_PROM_H
+
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+
+/* environment arguments from bootloader */
+extern unsigned long memsize, highmemsize;
+
+/* loongson-specific command line, env and memory initialization */
+extern char *prom_getenv(char *name);
+extern void __init prom_init_cmdline(void);
+
+#endif /* __ASM_MACH_LOONGSON1_PROM_H */
diff --git a/arch/mips/include/asm/mach-loongson1/regs-clk.h b/arch/mips/include/asm/mach-loongson1/regs-clk.h
new file mode 100644
index 0000000..7a09d6a
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/regs-clk.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson1 Clock Register Definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON1_REGS_CLK_H
+#define __ASM_MACH_LOONGSON1_REGS_CLK_H
+
+#define LS1_CLK_REG(x) ((void __iomem *)(LOONGSON1_CLK_BASE + (x)))
+
+#define LS1_CLK_PLL_FREQ LS1_CLK_REG(0x0)
+#define LS1_CLK_PLL_DIV LS1_CLK_REG(0x4)
+
+/* Clock PLL Divisor Register Bits */
+#define DIV_DC_EN (0x1 << 31)
+#define DIV_DC (0x1f << 26)
+#define DIV_CPU_EN (0x1 << 25)
+#define DIV_CPU (0x1f << 20)
+#define DIV_DDR_EN (0x1 << 19)
+#define DIV_DDR (0x1f << 14)
+
+#define DIV_DC_SHIFT (26)
+#define DIV_CPU_SHIFT (20)
+#define DIV_DDR_SHIFT (14)
+
+#endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */
diff --git a/arch/mips/include/asm/mach-loongson1/regs-intc.h b/arch/mips/include/asm/mach-loongson1/regs-intc.h
new file mode 100644
index 0000000..3c62411
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/regs-intc.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson1 Interrupt register definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON1_REGS_INTC_H
+#define __ASM_MACH_LOONGSON1_REGS_INTC_H
+
+#define LS1_INTC_REG(x) ((void __iomem *)(LOONGSON1_INTC_BASE \
+ + n * 0x18 + x))
+
+#define LS1_INTC_INTISR(n) LS1_INTC_REG(0x0)
+#define LS1_INTC_INTIEN(n) LS1_INTC_REG(0x4)
+#define LS1_INTC_INTSET(n) LS1_INTC_REG(0x8)
+#define LS1_INTC_INTCLR(n) LS1_INTC_REG(0xc)
+#define LS1_INTC_INTPOL(n) LS1_INTC_REG(0x10)
+#define LS1_INTC_INTEDGE(n) LS1_INTC_REG(0x14)
+
+#endif /* __ASM_MACH_LOONGSON1_REGS_INTC_H */
diff --git a/arch/mips/include/asm/mach-loongson1/regs-wdt.h b/arch/mips/include/asm/mach-loongson1/regs-wdt.h
new file mode 100644
index 0000000..2393dd7
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/regs-wdt.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Loongson1 Watchdog register definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON1_REGS_WDT_H
+#define __ASM_MACH_LOONGSON1_REGS_WDT_H
+
+#define LS1_WDT_REG(x) ((void __iomem *)(LOONGSON1_WDT_BASE + (x)))
+
+#define LS1_WDT_EN LS1_WDT_REG(0x0)
+#define LS1_WDT_SET LS1_WDT_REG(0x4)
+#define LS1_WDT_TIMER LS1_WDT_REG(0x8)
+
+#endif /* __ASM_MACH_LOONGSON1_REGS_WDT_H */
diff --git a/arch/mips/include/asm/mach-loongson1/war.h b/arch/mips/include/asm/mach-loongson1/war.h
new file mode 100644
index 0000000..e3680a8
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson1/war.h
@@ -0,0 +1,25 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
+ */
+#ifndef __ASM_MACH_LOONGSON1_WAR_H
+#define __ASM_MACH_LOONGSON1_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR 0
+#define R4600_V1_HIT_CACHEOP_WAR 0
+#define R4600_V2_HIT_CACHEOP_WAR 0
+#define R5432_CP0_INTERRUPT_WAR 0
+#define BCM1250_M3_WAR 0
+#define SIBYTE_1956_WAR 0
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
+#define TX49XX_ICACHE_INDEX_INV_WAR 0
+#define RM9000_CDEX_SMP_WAR 0
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
+#define R10000_LLSC_WAR 0
+#define MIPS34K_MISSED_ITLB_WAR 0
+
+#endif /* __ASM_MACH_LOONGSON1_WAR_H */
diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
index bc01a02..b53d642 100644
--- a/arch/mips/include/asm/module.h
+++ b/arch/mips/include/asm/module.h
@@ -116,6 +116,8 @@ search_module_dbetables(unsigned long addr)
#define MODULE_PROC_FAMILY "SB1 "
#elif defined CONFIG_CPU_LOONGSON2
#define MODULE_PROC_FAMILY "LOONGSON2 "
+#elif defined CONFIG_CPU_LOONGSON1
+#define MODULE_PROC_FAMILY "LOONGSON1 "
#elif defined CONFIG_CPU_CAVIUM_OCTEON
#define MODULE_PROC_FAMILY "OCTEON "
#elif defined CONFIG_CPU_XLR
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index 664bc13..98d4235 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -37,6 +37,8 @@
void (*cpu_wait)(void);
EXPORT_SYMBOL(cpu_wait);
+static void __cpuinit decode_configs(struct cpuinfo_mips *c);
+
static void r3081_wait(void)
{
unsigned long cfg = read_c0_conf();
@@ -191,6 +193,7 @@ void __init check_wait(void)
case CPU_CAVIUM_OCTEON2:
case CPU_JZRISC:
case CPU_XLR:
+ case CPU_LOONGSON1:
cpu_wait = r4k_wait;
break;
@@ -636,6 +639,18 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
MIPS_CPU_32FPR;
c->tlbsize = 64;
break;
+ case PRID_IMP_LOONGSON1:
+ decode_configs(c);
+
+ c->cputype = CPU_LOONGSON1;
+
+ switch (c->processor_id & PRID_REV_MASK) {
+ case PRID_REV_LOONGSON1B:
+ __cpu_name[cpu] = "Loongson 1B";
+ break;
+ }
+
+ break;
}
}
diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
index e5ad09a..e316b0e 100644
--- a/arch/mips/kernel/perf_event_mipsxx.c
+++ b/arch/mips/kernel/perf_event_mipsxx.c
@@ -1062,6 +1062,12 @@ init_hw_perf_events(void)
mipsxxcore_pmu.irq = irq;
mipspmu = &mipsxxcore_pmu;
break;
+ case CPU_LOONGSON1:
+ mipsxxcore_pmu.name = "mips/loongson1";
+ mipsxxcore_pmu.num_counters = counters;
+ mipsxxcore_pmu.irq = irq;
+ mipspmu = &mipsxxcore_pmu;
+ break;
default:
pr_cont("Either hardware does not support performance "
"counters, or not yet implemented.\n");
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 01eff7e..cd55823 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1241,6 +1241,7 @@ static inline void parity_protection_init(void)
break;
case CPU_5KC:
+ case CPU_LOONGSON1:
write_c0_ecc(0x80000000);
back_to_back_c0_hazard();
/* Set the PE bit (bit 31) in the c0_errctl register. */
diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson1/Kconfig
new file mode 100644
index 0000000..237fa21
--- /dev/null
+++ b/arch/mips/loongson1/Kconfig
@@ -0,0 +1,21 @@
+if MACH_LOONGSON1
+
+choice
+ prompt "Machine Type"
+
+config LOONGSON1_LS1B
+ bool "Loongson LS1B board"
+ select CEVT_R4K
+ select CSRC_R4K
+ select SYS_HAS_CPU_LOONGSON1B
+ select DMA_NONCOHERENT
+ select BOOT_ELF32
+ select IRQ_CPU
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_LITTLE_ENDIAN
+ select SYS_SUPPORTS_HIGHMEM
+ select SYS_HAS_EARLY_PRINTK
+
+endchoice
+
+endif # MACH_LOONGSON1
diff --git a/arch/mips/loongson1/Makefile b/arch/mips/loongson1/Makefile
new file mode 100644
index 0000000..e9123c2
--- /dev/null
+++ b/arch/mips/loongson1/Makefile
@@ -0,0 +1,11 @@
+#
+# Common code for all Loongson1 based systems
+#
+
+obj-$(CONFIG_MACH_LOONGSON1) += common/
+
+#
+# Loongson LS1B board
+#
+
+obj-$(CONFIG_LOONGSON1_LS1B) += ls1b/
diff --git a/arch/mips/loongson1/Platform b/arch/mips/loongson1/Platform
new file mode 100644
index 0000000..92804c6
--- /dev/null
+++ b/arch/mips/loongson1/Platform
@@ -0,0 +1,7 @@
+cflags-$(CONFIG_CPU_LOONGSON1) += \
+ $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
+ -Wa,-mips32r2 -Wa,--trap
+
+platform-$(CONFIG_MACH_LOONGSON1) += loongson1/
+cflags-$(CONFIG_MACH_LOONGSON1) += -I$(srctree)/arch/mips/include/asm/mach-loongson1
+load-$(CONFIG_LOONGSON1_LS1B) += 0xffffffff80010000
diff --git a/arch/mips/loongson1/common/Makefile b/arch/mips/loongson1/common/Makefile
new file mode 100644
index 0000000..b279770
--- /dev/null
+++ b/arch/mips/loongson1/common/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for common code of loongson1 based machines.
+#
+
+obj-y += clock.o irq.o platform.o prom.o reset.o setup.o
diff --git a/arch/mips/loongson1/common/clock.c b/arch/mips/loongson1/common/clock.c
new file mode 100644
index 0000000..7f4f28b
--- /dev/null
+++ b/arch/mips/loongson1/common/clock.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <asm/clock.h>
+#include <asm/time.h>
+
+#include <loongson1.h>
+
+static LIST_HEAD(clocks);
+static DEFINE_MUTEX(clocks_mutex);
+
+struct clk *clk_get(struct device *dev, const char *name)
+{
+ struct clk *c;
+ struct clk *ret = NULL;
+
+ mutex_lock(&clocks_mutex);
+ list_for_each_entry(c, &clocks, node) {
+ if (!strcmp(c->name, name)) {
+ ret = c;
+ break;
+ }
+ }
+ mutex_unlock(&clocks_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL(clk_get);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ return clk->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+static void pll_clk_init(struct clk *clk)
+{
+ u32 pll;
+
+ pll = __raw_readl(LS1_CLK_PLL_FREQ);
+ clk->rate = (12 + (pll & 0x3f)) * 33 / 2
+ + ((pll >> 8) & 0x3ff) * 33 / 1024 / 2;
+ clk->rate *= 1000000;
+}
+
+static void cpu_clk_init(struct clk *clk)
+{
+ u32 pll, ctrl;
+
+ pll = clk_get_rate(clk->parent);
+ ctrl = __raw_readl(LS1_CLK_PLL_DIV) & DIV_CPU;
+ clk->rate = pll / (ctrl >> DIV_CPU_SHIFT);
+}
+
+static void ddr_clk_init(struct clk *clk)
+{
+ u32 pll, ctrl;
+
+ pll = clk_get_rate(clk->parent);
+ ctrl = __raw_readl(LS1_CLK_PLL_DIV) & DIV_DDR;
+ clk->rate = pll / (ctrl >> DIV_DDR_SHIFT);
+}
+
+static void dc_clk_init(struct clk *clk)
+{
+ u32 pll, ctrl;
+
+ pll = clk_get_rate(clk->parent);
+ ctrl = __raw_readl(LS1_CLK_PLL_DIV) & DIV_DC;
+ clk->rate = pll / (ctrl >> DIV_DC_SHIFT);
+}
+
+static struct clk_ops pll_clk_ops = {
+ .init = pll_clk_init,
+};
+
+static struct clk_ops cpu_clk_ops = {
+ .init = cpu_clk_init,
+};
+
+static struct clk_ops ddr_clk_ops = {
+ .init = ddr_clk_init,
+};
+
+static struct clk_ops dc_clk_ops = {
+ .init = dc_clk_init,
+};
+
+static struct clk pll_clk = {
+ .name = "pll",
+ .ops = &pll_clk_ops,
+};
+
+static struct clk cpu_clk = {
+ .name = "cpu",
+ .parent = &pll_clk,
+ .ops = &cpu_clk_ops,
+};
+
+static struct clk ddr_clk = {
+ .name = "ddr",
+ .parent = &pll_clk,
+ .ops = &ddr_clk_ops,
+};
+
+static struct clk dc_clk = {
+ .name = "dc",
+ .parent = &pll_clk,
+ .ops = &dc_clk_ops,
+};
+
+int clk_register(struct clk *clk)
+{
+ mutex_lock(&clocks_mutex);
+ list_add(&clk->node, &clocks);
+ if (clk->ops->init)
+ clk->ops->init(clk);
+ mutex_unlock(&clocks_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+static struct clk *loongson1_clks[] = {
+ &pll_clk,
+ &cpu_clk,
+ &ddr_clk,
+ &dc_clk,
+};
+
+int __init loongson1_clock_init(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(loongson1_clks); i++)
+ clk_register(loongson1_clks[i]);
+
+ return 0;
+}
+
+void __init plat_time_init(void)
+{
+ struct clk *clk;
+
+ /* Initialize loongson1 clocks */
+ loongson1_clock_init();
+
+ /* setup mips r4k timer */
+ clk = clk_get(NULL, "cpu");
+ if (IS_ERR(clk))
+ panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
+
+ mips_hpt_frequency = clk_get_rate(clk) / 2;
+}
diff --git a/arch/mips/loongson1/common/irq.c b/arch/mips/loongson1/common/irq.c
new file mode 100644
index 0000000..a5dcabb
--- /dev/null
+++ b/arch/mips/loongson1/common/irq.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/irq_cpu.h>
+
+#include <loongson1.h>
+#include <irq.h>
+
+static void loongson1_irq_ack(struct irq_data *d)
+{
+ unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
+ unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
+
+ __raw_writel(__raw_readl(LS1_INTC_INTCLR(n))
+ | (1 << bit), LS1_INTC_INTCLR(n));
+}
+
+static void loongson1_irq_mask(struct irq_data *d)
+{
+ unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
+ unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
+
+ __raw_writel(__raw_readl(LS1_INTC_INTIEN(n))
+ & ~(1 << bit), LS1_INTC_INTIEN(n));
+}
+
+static void loongson1_irq_mask_ack(struct irq_data *d)
+{
+ unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
+ unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
+
+ __raw_writel(__raw_readl(LS1_INTC_INTIEN(n))
+ & ~(1 << bit), LS1_INTC_INTIEN(n));
+ __raw_writel(__raw_readl(LS1_INTC_INTCLR(n))
+ | (1 << bit), LS1_INTC_INTCLR(n));
+}
+
+static void loongson1_irq_unmask(struct irq_data *d)
+{
+ unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
+ unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
+
+ __raw_writel(__raw_readl(LS1_INTC_INTIEN(n))
+ | (1 << bit), LS1_INTC_INTIEN(n));
+}
+
+static struct irq_chip loongson1_irq_chip = {
+ .name = "LOONGSON1-INTC",
+ .irq_ack = loongson1_irq_ack,
+ .irq_mask = loongson1_irq_mask,
+ .irq_mask_ack = loongson1_irq_mask_ack,
+ .irq_unmask = loongson1_irq_unmask,
+};
+
+static void loongson1_irq_dispatch(int n)
+{
+ u32 int_status, irq;
+
+ /* Get pending sources, masked by current enables */
+ int_status = __raw_readl(LS1_INTC_INTISR(n)) &
+ __raw_readl(LS1_INTC_INTIEN(n));
+
+ if (int_status) {
+ irq = LOONGSON1_IRQ(n, __ffs(int_status));
+ do_IRQ(irq);
+ }
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending;
+
+ pending = read_c0_cause() & read_c0_status() & ST0_IM;
+
+ if (pending & CAUSEF_IP7)
+ do_IRQ(TIMER_IRQ);
+ else if (pending & CAUSEF_IP2)
+ loongson1_irq_dispatch(0); /* INT0 */
+ else if (pending & CAUSEF_IP3)
+ loongson1_irq_dispatch(1); /* INT1 */
+ else if (pending & CAUSEF_IP4)
+ loongson1_irq_dispatch(2); /* INT2 */
+ else if (pending & CAUSEF_IP5)
+ loongson1_irq_dispatch(3); /* INT3 */
+ else if (pending & CAUSEF_IP6)
+ loongson1_irq_dispatch(4); /* INT4 */
+ else
+ spurious_interrupt();
+
+}
+
+struct irqaction cascade_irqaction = {
+ .handler = no_action,
+ .name = "cascade",
+ .flags = IRQF_NO_THREAD,
+};
+
+static void __init loongson1_irq_init(int base)
+{
+ int n;
+
+ /* Disable interrupts and clear pending,
+ * setup all IRQs as high level triggered
+ */
+ for (n = 0; n < 4; n++) {
+ __raw_writel(0x0, LS1_INTC_INTIEN(n));
+ __raw_writel(0xffffffff, LS1_INTC_INTCLR(n));
+ __raw_writel(0xffffffff, LS1_INTC_INTPOL(n));
+ __raw_writel(0x0, LS1_INTC_INTEDGE(n));
+ }
+
+
+ for (n = base; n < NR_IRQS; n++) {
+ irq_set_chip_and_handler(n, &loongson1_irq_chip,
+ handle_level_irq);
+ }
+
+ setup_irq(INT0_IRQ, &cascade_irqaction);
+ setup_irq(INT1_IRQ, &cascade_irqaction);
+ setup_irq(INT2_IRQ, &cascade_irqaction);
+ setup_irq(INT3_IRQ, &cascade_irqaction);
+}
+
+void __init arch_init_irq(void)
+{
+ mips_cpu_irq_init();
+ loongson1_irq_init(LOONGSON1_IRQ_BASE);
+}
diff --git a/arch/mips/loongson1/common/platform.c b/arch/mips/loongson1/common/platform.c
new file mode 100644
index 0000000..c93028e
--- /dev/null
+++ b/arch/mips/loongson1/common/platform.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/serial_8250.h>
+
+#include <loongson1.h>
+
+#define LOONGSON1_UART_PORT(_id) \
+ { \
+ .mapbase = LOONGSON1_UART ## _id ## _BASE, \
+ .membase = (void *)(LOONGSON1_UART ## _id ## _BASE), \
+ .irq = LOONGSON1_UART ## _id ## _IRQ, \
+ .iotype = UPIO_MEM, \
+ .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, \
+ .type = PORT_16550A, \
+ }
+
+static struct plat_serial8250_port loongson1_serial8250_port[] = {
+ LOONGSON1_UART_PORT(0),
+ {},
+};
+
+struct platform_device loongson1_uart_device = {
+ .name = "serial8250",
+ .id = PLAT8250_DEV_PLATFORM,
+ .dev = {
+ .platform_data = loongson1_serial8250_port,
+ },
+};
+
+void __init loongson1_serial_setup(void)
+{
+ struct clk *clk;
+ struct plat_serial8250_port *p;
+
+ clk = clk_get(NULL, "dc");
+ if (IS_ERR(clk))
+ panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
+
+ for (p = loongson1_serial8250_port; p->flags != 0; ++p)
+ p->uartclk = clk_get_rate(clk);
+}
diff --git a/arch/mips/loongson1/common/prom.c b/arch/mips/loongson1/common/prom.c
new file mode 100644
index 0000000..70791f1
--- /dev/null
+++ b/arch/mips/loongson1/common/prom.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * Modified from arch/mips/pnx833x/common/prom.c.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/serial_reg.h>
+#include <asm/bootinfo.h>
+
+#include <loongson1.h>
+#include <prom.h>
+
+int prom_argc;
+char **prom_argv, **prom_envp;
+unsigned long memsize, highmemsize;
+
+char *prom_getenv(char *envname)
+{
+ char **env = prom_envp;
+ int i;
+
+ i = strlen(envname);
+
+ while (*env) {
+ if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=')
+ return *env + i + 1;
+ env++;
+ }
+
+ return 0;
+}
+
+static inline unsigned long env_or_default(char *env, unsigned long dfl)
+{
+ char *str = prom_getenv(env);
+ return str ? simple_strtol(str, 0, 0) : dfl;
+}
+
+void __init prom_init_cmdline(void)
+{
+ char *c = &(arcs_cmdline[0]);
+ int i;
+
+ for (i = 1; i < prom_argc; i++) {
+ strcpy(c, prom_argv[i]);
+ c += strlen(prom_argv[i]);
+ if (i < prom_argc-1)
+ *c++ = ' ';
+ }
+ *c = 0;
+}
+
+void __init prom_init(void)
+{
+ prom_argc = fw_arg0;
+ prom_argv = (char **)fw_arg1;
+ prom_envp = (char **)fw_arg2;
+
+ prom_init_cmdline();
+
+ memsize = env_or_default("memsize", DEFAULT_MEMSIZE);
+ highmemsize = env_or_default("highmemsize", 0x0);
+}
+
+void __init prom_free_prom_memory(void)
+{
+}
+
+#define UART_BASE LOONGSON1_UART0_BASE
+#define PORT(base, offset) (u8 *)(base + offset)
+
+void __init prom_putchar(char c)
+{
+ int timeout;
+
+ timeout = 1024;
+
+ while (((readb(PORT(UART_BASE, UART_LSR)) & UART_LSR_THRE) == 0)
+ && (timeout-- > 0))
+ ;
+
+ writeb(c, PORT(UART_BASE, UART_TX));
+}
diff --git a/arch/mips/loongson1/common/reset.c b/arch/mips/loongson1/common/reset.c
new file mode 100644
index 0000000..75f550f
--- /dev/null
+++ b/arch/mips/loongson1/common/reset.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/pm.h>
+#include <asm/reboot.h>
+
+#include <loongson1.h>
+
+static void loongson1_restart(char *command)
+{
+ __raw_writel(0x1, LS1_WDT_EN);
+ __raw_writel(0x5000000, LS1_WDT_TIMER);
+ __raw_writel(0x1, LS1_WDT_SET);
+}
+
+static void loongson1_halt(void)
+{
+ pr_notice("\n\n** You can safely turn off the power now **\n\n");
+ while (1) {
+ if (cpu_wait)
+ cpu_wait();
+ }
+}
+
+static void loongson1_power_off(void)
+{
+ loongson1_halt();
+}
+
+static int __init loongson1_reboot_setup(void)
+{
+ _machine_restart = loongson1_restart;
+ _machine_halt = loongson1_halt;
+ pm_power_off = loongson1_power_off;
+
+ return 0;
+}
+
+arch_initcall(loongson1_reboot_setup);
diff --git a/arch/mips/loongson1/common/setup.c b/arch/mips/loongson1/common/setup.c
new file mode 100644
index 0000000..62128cc
--- /dev/null
+++ b/arch/mips/loongson1/common/setup.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <asm/bootinfo.h>
+
+#include <prom.h>
+
+void __init plat_mem_setup(void)
+{
+ add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
+}
+
+const char *get_system_type(void)
+{
+ unsigned int processor_id = (¤t_cpu_data)->processor_id;
+
+ switch (processor_id & PRID_REV_MASK) {
+ case PRID_REV_LOONGSON1B:
+ return "LOONGSON LS1B";
+ default:
+ return "LOONGSON (unknown)";
+ }
+}
diff --git a/arch/mips/loongson1/ls1b/Makefile b/arch/mips/loongson1/ls1b/Makefile
new file mode 100644
index 0000000..891eac4
--- /dev/null
+++ b/arch/mips/loongson1/ls1b/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for loongson1B based machines.
+#
+
+obj-y += board.o
diff --git a/arch/mips/loongson1/ls1b/board.c b/arch/mips/loongson1/ls1b/board.c
new file mode 100644
index 0000000..b1a602f
--- /dev/null
+++ b/arch/mips/loongson1/ls1b/board.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <platform.h>
+
+#include <linux/serial_8250.h>
+#include <loongson1.h>
+
+static struct platform_device *loongson1_platform_devices[] __initdata = {
+ &loongson1_uart_device,
+};
+
+static int __init loongson1_platform_init(void)
+{
+ int err;
+
+ loongson1_serial_setup();
+
+ err = platform_add_devices(loongson1_platform_devices,
+ ARRAY_SIZE(loongson1_platform_devices));
+ return err;
+}
+
+arch_initcall(loongson1_platform_init);
diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
index d1f2d4c..99216f0 100644
--- a/arch/mips/oprofile/common.c
+++ b/arch/mips/oprofile/common.c
@@ -89,6 +89,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
case CPU_R10000:
case CPU_R12000:
case CPU_R14000:
+ case CPU_LOONGSON1:
lmodel = &op_model_mipsxx_ops;
break;
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 54759f1..03be670 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -365,6 +365,10 @@ static int __init mipsxx_init(void)
op_model_mipsxx_ops.cpu_type = "mips/sb1";
break;
+ case CPU_LOONGSON1:
+ op_model_mipsxx_ops.cpu_type = "mips/loongson1";
+ break;
+
default:
printk(KERN_ERR "Profiling unsupported for this CPU\n");
--
1.7.4.1
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 1/2] MIPS: Add basic support for Loongson1B (UPDATED)
2011-09-24 6:21 [PATCH 1/2] MIPS: Add basic support " keguang.zhang
@ 2011-09-25 5:27 ` wu zhangjin
2011-09-25 13:40 ` Shane McDonald
2011-09-26 9:00 ` Kelvin Cheung
0 siblings, 2 replies; 8+ messages in thread
From: wu zhangjin @ 2011-09-25 5:27 UTC (permalink / raw)
To: keguang.zhang; +Cc: linux-mips, linux-kernel, ralf, r0bertz, chenj
On Sat, Sep 24, 2011 at 2:21 PM, <keguang.zhang@gmail.com> wrote:
> From: Kelvin Cheung <keguang.zhang@gmail.com>
>
> This patch adds basic support for Loongson1B
> including serial port, timer and interrupt handler.
>
> Loongson 1B is a 32-bit SoC designed by Institute of
> Computing Technology (ICT), Chinese Academy of Sciences (CAS),
> which implements the MIPS32 release 2 instruction set.
>
> Signed-off-by: Kelvin Cheung <keguang.zhang@gmail.com>
> ---
> arch/mips/Kbuild.platforms | 1 +
> arch/mips/Kconfig | 31 ++++
> arch/mips/include/asm/cpu.h | 3 +-
> arch/mips/include/asm/mach-loongson1/irq.h | 70 +++++++++
> arch/mips/include/asm/mach-loongson1/loongson1.h | 48 +++++++
> arch/mips/include/asm/mach-loongson1/platform.h | 20 +++
> arch/mips/include/asm/mach-loongson1/prom.h | 24 +++
> arch/mips/include/asm/mach-loongson1/regs-clk.h | 32 ++++
> arch/mips/include/asm/mach-loongson1/regs-intc.h | 25 ++++
> arch/mips/include/asm/mach-loongson1/regs-wdt.h | 21 +++
> arch/mips/include/asm/mach-loongson1/war.h | 25 ++++
> arch/mips/include/asm/module.h | 2 +
> arch/mips/kernel/cpu-probe.c | 15 ++
> arch/mips/kernel/perf_event_mipsxx.c | 6 +
> arch/mips/kernel/traps.c | 1 +
> arch/mips/loongson1/Kconfig | 21 +++
> arch/mips/loongson1/Makefile | 11 ++
> arch/mips/loongson1/Platform | 7 +
> arch/mips/loongson1/common/Makefile | 5 +
> arch/mips/loongson1/common/clock.c | 165 ++++++++++++++++++++++
> arch/mips/loongson1/common/irq.c | 136 ++++++++++++++++++
> arch/mips/loongson1/common/platform.c | 50 +++++++
> arch/mips/loongson1/common/prom.c | 88 ++++++++++++
> arch/mips/loongson1/common/reset.c | 46 ++++++
> arch/mips/loongson1/common/setup.c | 29 ++++
> arch/mips/loongson1/ls1b/Makefile | 5 +
> arch/mips/loongson1/ls1b/board.c | 30 ++++
> arch/mips/oprofile/common.c | 1 +
> arch/mips/oprofile/op_model_mipsxx.c | 4 +
> 29 files changed, 921 insertions(+), 1 deletions(-)
> create mode 100644 arch/mips/include/asm/mach-loongson1/irq.h
> create mode 100644 arch/mips/include/asm/mach-loongson1/loongson1.h
> create mode 100644 arch/mips/include/asm/mach-loongson1/platform.h
> create mode 100644 arch/mips/include/asm/mach-loongson1/prom.h
> create mode 100644 arch/mips/include/asm/mach-loongson1/regs-clk.h
> create mode 100644 arch/mips/include/asm/mach-loongson1/regs-intc.h
> create mode 100644 arch/mips/include/asm/mach-loongson1/regs-wdt.h
> create mode 100644 arch/mips/include/asm/mach-loongson1/war.h
> create mode 100644 arch/mips/loongson1/Kconfig
> create mode 100644 arch/mips/loongson1/Makefile
> create mode 100644 arch/mips/loongson1/Platform
> create mode 100644 arch/mips/loongson1/common/Makefile
> create mode 100644 arch/mips/loongson1/common/clock.c
> create mode 100644 arch/mips/loongson1/common/irq.c
> create mode 100644 arch/mips/loongson1/common/platform.c
> create mode 100644 arch/mips/loongson1/common/prom.c
> create mode 100644 arch/mips/loongson1/common/reset.c
> create mode 100644 arch/mips/loongson1/common/setup.c
> create mode 100644 arch/mips/loongson1/ls1b/Makefile
> create mode 100644 arch/mips/loongson1/ls1b/board.c
>
> diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
> index 5ce8029..d64786d 100644
> --- a/arch/mips/Kbuild.platforms
> +++ b/arch/mips/Kbuild.platforms
> @@ -14,6 +14,7 @@ platforms += jz4740
> platforms += lantiq
> platforms += lasat
> platforms += loongson
> +platforms += loongson1
> platforms += mipssim
> platforms += mti-malta
> platforms += netlogic
> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
> index d9b8ea8..4c6ad4f 100644
> --- a/arch/mips/Kconfig
> +++ b/arch/mips/Kconfig
> @@ -262,6 +262,17 @@ config MACH_LOONGSON
> Chinese Academy of Sciences (CAS) in the People's Republic
> of China. The chief architect is Professor Weiwu Hu.
>
> +config MACH_LOONGSON1
> + bool "Loongson1 family of machines"
> + select SYS_SUPPORTS_ZBOOT
> + help
> + This enables the support of Loongson1 family of machines.
> +
> + Loongson1 is a family of 32-bit MIPS-compatible SoCs.
> + developed at Institute of Computing Technology (ICT),
> + Chinese Academy of Sciences (CAS) in the People's Republic
> + of China.
> +
> config MIPS_MALTA
> bool "MIPS Malta board"
> select ARCH_MAY_HAVE_PC_FDC
> @@ -808,6 +819,7 @@ source "arch/mips/txx9/Kconfig"
> source "arch/mips/vr41xx/Kconfig"
> source "arch/mips/cavium-octeon/Kconfig"
> source "arch/mips/loongson/Kconfig"
> +source "arch/mips/loongson1/Kconfig"
> source "arch/mips/netlogic/Kconfig"
>
> endmenu
> @@ -1201,6 +1213,14 @@ config CPU_LOONGSON2F
> have a similar programming interface with FPGA northbridge used in
> Loongson2E.
>
> +config CPU_LOONGSON1B
> + bool "Loongson 1B"
> + depends on SYS_HAS_CPU_LOONGSON1B
> + select CPU_LOONGSON1
> + help
> + The Loongson 1B is a 32-bit SoC, which implements the MIPS32
> + release 2 instruction set.
> +
> config CPU_MIPS32_R1
> bool "MIPS32 Release 1"
> depends on SYS_HAS_CPU_MIPS32_R1
> @@ -1529,6 +1549,14 @@ config CPU_LOONGSON2
> select CPU_SUPPORTS_64BIT_KERNEL
> select CPU_SUPPORTS_HIGHMEM
>
> +config CPU_LOONGSON1
> + bool
> + select CPU_MIPS32
> + select CPU_MIPSR2
> + select CPU_HAS_PREFETCH
> + select CPU_SUPPORTS_32BIT_KERNEL
> + select CPU_SUPPORTS_HIGHMEM
> +
> config SYS_HAS_CPU_LOONGSON2E
> bool
>
> @@ -1538,6 +1566,9 @@ config SYS_HAS_CPU_LOONGSON2F
> select CPU_SUPPORTS_ADDRWINCFG if 64BIT
> select CPU_SUPPORTS_UNCACHED_ACCELERATED
>
> +config SYS_HAS_CPU_LOONGSON1B
> + bool
> +
> config SYS_HAS_CPU_MIPS32_R1
> bool
>
> diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
> index 5f95a4b..975f372 100644
> --- a/arch/mips/include/asm/cpu.h
> +++ b/arch/mips/include/asm/cpu.h
> @@ -191,6 +191,7 @@
> #define PRID_REV_34K_V1_0_2 0x0022
> #define PRID_REV_LOONGSON2E 0x0002
> #define PRID_REV_LOONGSON2F 0x0003
> +#define PRID_REV_LOONGSON1B 0x0020
>
> /*
> * Older processors used to encode processor version and revision in two
> @@ -253,7 +254,7 @@ enum cpu_type_enum {
> */
> CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
> CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
> - CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC,
> + CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1,
>
> /*
> * MIPS64 class processors
> diff --git a/arch/mips/include/asm/mach-loongson1/irq.h b/arch/mips/include/asm/mach-loongson1/irq.h
> new file mode 100644
> index 0000000..e8fed7a
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson1/irq.h
> @@ -0,0 +1,70 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * IRQ mappings for Loongson1.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +
> +#ifndef __ASM_MACH_LOONGSON1_IRQ_H
> +#define __ASM_MACH_LOONGSON1_IRQ_H
> +
> +/*
> + * CPU core Interrupt Numbers
> + */
> +#define MIPS_CPU_IRQ_BASE 0
> +#define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x))
> +#define SOFTINT0_IRQ MIPS_CPU_IRQ(0)
> +#define SOFTINT1_IRQ MIPS_CPU_IRQ(1)
> +#define INT0_IRQ MIPS_CPU_IRQ(2)
> +#define INT1_IRQ MIPS_CPU_IRQ(3)
> +#define INT2_IRQ MIPS_CPU_IRQ(4)
> +#define INT3_IRQ MIPS_CPU_IRQ(5)
> +#define INT4_IRQ MIPS_CPU_IRQ(6)
> +#define TIMER_IRQ MIPS_CPU_IRQ(7) /* cpu timer */
> +
> +/*
> + * INT0~3 Interrupt Numbers
> + */
> +#define LOONGSON1_IRQ_BASE 8
> +#define LOONGSON1_IRQ(n, x) (LOONGSON1_IRQ_BASE + (n << 5) + (x))
> +
> +#define LOONGSON1_UART0_IRQ LOONGSON1_IRQ(0, 2)
> +#define LOONGSON1_UART1_IRQ LOONGSON1_IRQ(0, 3)
> +#define LOONGSON1_UART2_IRQ LOONGSON1_IRQ(0, 4)
> +#define LOONGSON1_UART3_IRQ LOONGSON1_IRQ(0, 5)
> +#define LOONGSON1_CAN0_IRQ LOONGSON1_IRQ(0, 6)
> +#define LOONGSON1_CAN1_IRQ LOONGSON1_IRQ(0, 7)
> +#define LOONGSON1_SPI0_IRQ LOONGSON1_IRQ(0, 8)
> +#define LOONGSON1_SPI1_IRQ LOONGSON1_IRQ(0, 9)
> +#define LOONGSON1_AC97_IRQ LOONGSON1_IRQ(0, 10)
> +#define LOONGSON1_DMA0_IRQ LOONGSON1_IRQ(0, 13)
> +#define LOONGSON1_DMA1_IRQ LOONGSON1_IRQ(0, 14)
> +#define LOONGSON1_DMA2_IRQ LOONGSON1_IRQ(0, 15)
> +#define LOONGSON1_PWM0_IRQ LOONGSON1_IRQ(0, 17)
> +#define LOONGSON1_PWM1_IRQ LOONGSON1_IRQ(0, 18)
> +#define LOONGSON1_PWM2_IRQ LOONGSON1_IRQ(0, 19)
> +#define LOONGSON1_PWM3_IRQ LOONGSON1_IRQ(0, 20)
> +#define LOONGSON1_RTC_INT0_IRQ LOONGSON1_IRQ(0, 21)
> +#define LOONGSON1_RTC_INT1_IRQ LOONGSON1_IRQ(0, 22)
> +#define LOONGSON1_RTC_INT2_IRQ LOONGSON1_IRQ(0, 23)
> +#define LOONGSON1_TOY_INT0_IRQ LOONGSON1_IRQ(0, 24)
> +#define LOONGSON1_TOY_INT1_IRQ LOONGSON1_IRQ(0, 25)
> +#define LOONGSON1_TOY_INT2_IRQ LOONGSON1_IRQ(0, 26)
> +#define LOONGSON1_RTC_TICK_IRQ LOONGSON1_IRQ(0, 27)
> +#define LOONGSON1_TOY_TICK_IRQ LOONGSON1_IRQ(0, 28)
> +#define LOONGSON1_UART4_IRQ LOONGSON1_IRQ(0, 29)
> +#define LOONGSON1_UART5_IRQ LOONGSON1_IRQ(0, 30)
> +
> +#define LOONGSON1_OHCI_IRQ LOONGSON1_IRQ(1, 0)
> +#define LOONGSON1_EHCI_IRQ LOONGSON1_IRQ(1, 1)
> +#define LOONGSON1_GMAC0_IRQ LOONGSON1_IRQ(1, 2)
> +#define LOONGSON1_GMAC1_IRQ LOONGSON1_IRQ(1, 3)
> +
> +#define NR_IRQS LOONGSON1_GMAC1_IRQ
Are you using TAB above?
> +
> +#endif /* __ASM_MACH_LOONGSON1_IRQ_H */
> diff --git a/arch/mips/include/asm/mach-loongson1/loongson1.h b/arch/mips/include/asm/mach-loongson1/loongson1.h
> new file mode 100644
> index 0000000..466136d
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson1/loongson1.h
> @@ -0,0 +1,48 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * Register mappings for Loongson1.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +
> +#ifndef __ASM_MACH_LOONGSON1_LOONGSON1_H
> +#define __ASM_MACH_LOONGSON1_LOONGSON1_H
> +
> +#define DEFAULT_MEMSIZE (256) /* If no memsize provided */
> +
> +/* Loongson1 Register Bases */
> +/* All regs are accessed in KSEG1 */
> +#define LOONGSON1_REGBASE (0xa0000000ul + 0x1fe00000ul)
> +
> +#define LOONGSON1_INTC_BASE (0xbfd01040)
> +#define LOONGSON1_USB_BASE (0xbfe00000)
> +#define LOONGSON1_GMAC0_BASE (0xbfe10000)
> +#define LOONGSON1_GMAC1_BASE (0xbfe20000)
> +#define LOONGSON1_UART0_BASE (0xbfe40000)
> +#define LOONGSON1_UART1_BASE (0xbfe44000)
> +#define LOONGSON1_UART2_BASE (0xbfe48000)
> +#define LOONGSON1_UART3_BASE (0xbfe4c000)
> +#define LOONGSON1_UART4_BASE (0xbfe6c000)
> +#define LOONGSON1_UART5_BASE (0xbfe7c000)
> +#define LOONGSON1_CAN0_BASE (0xbfe50000)
> +#define LOONGSON1_CAN1_BASE (0xbfe54000)
> +#define LOONGSON1_I2C0_BASE (0xbfe58000)
> +#define LOONGSON1_I2C1_BASE (0xbfe68000)
> +#define LOONGSON1_I2C2_BASE (0xbfe70000)
> +#define LOONGSON1_PWM_BASE (0xbfe5c000)
> +#define LOONGSON1_WDT_BASE (0xbfe5c060)
> +#define LOONGSON1_RTC_BASE (0xbfe64000)
> +#define LOONGSON1_AC97_BASE (0xbfe74000)
> +#define LOONGSON1_NAND_BASE (0xbfe78000)
> +#define LOONGSON1_CLK_BASE (0xbfe78030)
> +
> +#include <regs-clk.h>
> +#include <regs-intc.h>
> +#include <regs-wdt.h>
> +
> +#endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */
> diff --git a/arch/mips/include/asm/mach-loongson1/platform.h b/arch/mips/include/asm/mach-loongson1/platform.h
> new file mode 100644
> index 0000000..db4f02e
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson1/platform.h
> @@ -0,0 +1,20 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +
> +#ifndef __ASM_MACH_LOONGSON1_PLATFORM_H
> +#define __ASM_MACH_LOONGSON1_PLATFORM_H
> +
> +#include <linux/platform_device.h>
> +
> +extern struct platform_device loongson1_uart_device;
> +
> +void loongson1_serial_setup(void);
> +
> +#endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */
> diff --git a/arch/mips/include/asm/mach-loongson1/prom.h b/arch/mips/include/asm/mach-loongson1/prom.h
> new file mode 100644
> index 0000000..b871dc4
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson1/prom.h
> @@ -0,0 +1,24 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#ifndef __ASM_MACH_LOONGSON1_PROM_H
> +#define __ASM_MACH_LOONGSON1_PROM_H
> +
> +#include <linux/io.h>
> +#include <linux/init.h>
> +#include <linux/irq.h>
> +
> +/* environment arguments from bootloader */
> +extern unsigned long memsize, highmemsize;
> +
> +/* loongson-specific command line, env and memory initialization */
> +extern char *prom_getenv(char *name);
> +extern void __init prom_init_cmdline(void);
> +
> +#endif /* __ASM_MACH_LOONGSON1_PROM_H */
> diff --git a/arch/mips/include/asm/mach-loongson1/regs-clk.h b/arch/mips/include/asm/mach-loongson1/regs-clk.h
> new file mode 100644
> index 0000000..7a09d6a
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson1/regs-clk.h
> @@ -0,0 +1,32 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * Loongson1 Clock Register Definitions.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#ifndef __ASM_MACH_LOONGSON1_REGS_CLK_H
> +#define __ASM_MACH_LOONGSON1_REGS_CLK_H
> +
> +#define LS1_CLK_REG(x) ((void __iomem *)(LOONGSON1_CLK_BASE + (x)))
"volatile" keyword may be required for __iomem access, the same to the
following similar usage.
Considering a scene is(LS1_XXX_REG(X) doesn't really exist):
LS1_XXX_REG(X) = 0; /* put cpu into idle and wait interrupt */
LS1_XXX_REG(X) = 7; /* recover the cpu frequency to the highest */
If no "volatile" keyword indicated, the above two lines will be
intelligently but wrongly removed by compiler.
> +
> +#define LS1_CLK_PLL_FREQ LS1_CLK_REG(0x0)
> +#define LS1_CLK_PLL_DIV LS1_CLK_REG(0x4)
> +
> +/* Clock PLL Divisor Register Bits */
> +#define DIV_DC_EN (0x1 << 31)
> +#define DIV_DC (0x1f << 26)
> +#define DIV_CPU_EN (0x1 << 25)
> +#define DIV_CPU (0x1f << 20)
> +#define DIV_DDR_EN (0x1 << 19)
> +#define DIV_DDR (0x1f << 14)
The above exist format violation, SPACE, TAB?
> +
> +#define DIV_DC_SHIFT (26)
> +#define DIV_CPU_SHIFT (20)
> +#define DIV_DDR_SHIFT (14)
parenthesis may be not required for the scenes.
> +
> +#endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */
> diff --git a/arch/mips/include/asm/mach-loongson1/regs-intc.h b/arch/mips/include/asm/mach-loongson1/regs-intc.h
> new file mode 100644
> index 0000000..3c62411
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson1/regs-intc.h
> @@ -0,0 +1,25 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * Loongson1 Interrupt register definitions.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#ifndef __ASM_MACH_LOONGSON1_REGS_INTC_H
> +#define __ASM_MACH_LOONGSON1_REGS_INTC_H
> +
> +#define LS1_INTC_REG(x) ((void __iomem *)(LOONGSON1_INTC_BASE \
> + + n * 0x18 + x))
This may be better:
#define LS1_INTC_REG(x) \
((volatile void __iomem *)(LOONGSON1_INTC_BASE + (n * 0x18) + x))
> +
> +#define LS1_INTC_INTISR(n) LS1_INTC_REG(0x0)
> +#define LS1_INTC_INTIEN(n) LS1_INTC_REG(0x4)
> +#define LS1_INTC_INTSET(n) LS1_INTC_REG(0x8)
> +#define LS1_INTC_INTCLR(n) LS1_INTC_REG(0xc)
> +#define LS1_INTC_INTPOL(n) LS1_INTC_REG(0x10)
> +#define LS1_INTC_INTEDGE(n) LS1_INTC_REG(0x14)
> +
> +#endif /* __ASM_MACH_LOONGSON1_REGS_INTC_H */
> diff --git a/arch/mips/include/asm/mach-loongson1/regs-wdt.h b/arch/mips/include/asm/mach-loongson1/regs-wdt.h
> new file mode 100644
> index 0000000..2393dd7
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson1/regs-wdt.h
> @@ -0,0 +1,21 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * Loongson1 Watchdog register definitions.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#ifndef __ASM_MACH_LOONGSON1_REGS_WDT_H
> +#define __ASM_MACH_LOONGSON1_REGS_WDT_H
> +
> +#define LS1_WDT_REG(x) ((void __iomem *)(LOONGSON1_WDT_BASE + (x)))
> +
> +#define LS1_WDT_EN LS1_WDT_REG(0x0)
> +#define LS1_WDT_SET LS1_WDT_REG(0x4)
> +#define LS1_WDT_TIMER LS1_WDT_REG(0x8)
> +
> +#endif /* __ASM_MACH_LOONGSON1_REGS_WDT_H */
> diff --git a/arch/mips/include/asm/mach-loongson1/war.h b/arch/mips/include/asm/mach-loongson1/war.h
> new file mode 100644
> index 0000000..e3680a8
> --- /dev/null
> +++ b/arch/mips/include/asm/mach-loongson1/war.h
> @@ -0,0 +1,25 @@
> +/*
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License. See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
> + */
> +#ifndef __ASM_MACH_LOONGSON1_WAR_H
> +#define __ASM_MACH_LOONGSON1_WAR_H
> +
> +#define R4600_V1_INDEX_ICACHEOP_WAR 0
> +#define R4600_V1_HIT_CACHEOP_WAR 0
> +#define R4600_V2_HIT_CACHEOP_WAR 0
> +#define R5432_CP0_INTERRUPT_WAR 0
> +#define BCM1250_M3_WAR 0
> +#define SIBYTE_1956_WAR 0
> +#define MIPS4K_ICACHE_REFILL_WAR 0
> +#define MIPS_CACHE_SYNC_WAR 0
> +#define TX49XX_ICACHE_INDEX_INV_WAR 0
> +#define RM9000_CDEX_SMP_WAR 0
> +#define ICACHE_REFILLS_WORKAROUND_WAR 0
> +#define R10000_LLSC_WAR 0
> +#define MIPS34K_MISSED_ITLB_WAR 0
> +
> +#endif /* __ASM_MACH_LOONGSON1_WAR_H */
> diff --git a/arch/mips/include/asm/module.h b/arch/mips/include/asm/module.h
> index bc01a02..b53d642 100644
> --- a/arch/mips/include/asm/module.h
> +++ b/arch/mips/include/asm/module.h
> @@ -116,6 +116,8 @@ search_module_dbetables(unsigned long addr)
> #define MODULE_PROC_FAMILY "SB1 "
> #elif defined CONFIG_CPU_LOONGSON2
> #define MODULE_PROC_FAMILY "LOONGSON2 "
> +#elif defined CONFIG_CPU_LOONGSON1
> +#define MODULE_PROC_FAMILY "LOONGSON1 "
> #elif defined CONFIG_CPU_CAVIUM_OCTEON
> #define MODULE_PROC_FAMILY "OCTEON "
> #elif defined CONFIG_CPU_XLR
> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
> index 664bc13..98d4235 100644
> --- a/arch/mips/kernel/cpu-probe.c
> +++ b/arch/mips/kernel/cpu-probe.c
> @@ -37,6 +37,8 @@
> void (*cpu_wait)(void);
> EXPORT_SYMBOL(cpu_wait);
>
> +static void __cpuinit decode_configs(struct cpuinfo_mips *c);
> +
> static void r3081_wait(void)
> {
> unsigned long cfg = read_c0_conf();
> @@ -191,6 +193,7 @@ void __init check_wait(void)
> case CPU_CAVIUM_OCTEON2:
> case CPU_JZRISC:
> case CPU_XLR:
> + case CPU_LOONGSON1:
> cpu_wait = r4k_wait;
> break;
>
> @@ -636,6 +639,18 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
> MIPS_CPU_32FPR;
> c->tlbsize = 64;
> break;
> + case PRID_IMP_LOONGSON1:
> + decode_configs(c);
> +
> + c->cputype = CPU_LOONGSON1;
> +
> + switch (c->processor_id & PRID_REV_MASK) {
> + case PRID_REV_LOONGSON1B:
> + __cpu_name[cpu] = "Loongson 1B";
> + break;
> + }
> +
> + break;
> }
> }
>
> diff --git a/arch/mips/kernel/perf_event_mipsxx.c b/arch/mips/kernel/perf_event_mipsxx.c
> index e5ad09a..e316b0e 100644
> --- a/arch/mips/kernel/perf_event_mipsxx.c
> +++ b/arch/mips/kernel/perf_event_mipsxx.c
> @@ -1062,6 +1062,12 @@ init_hw_perf_events(void)
> mipsxxcore_pmu.irq = irq;
> mipspmu = &mipsxxcore_pmu;
> break;
> + case CPU_LOONGSON1:
> + mipsxxcore_pmu.name = "mips/loongson1";
> + mipsxxcore_pmu.num_counters = counters;
> + mipsxxcore_pmu.irq = irq;
> + mipspmu = &mipsxxcore_pmu;
> + break;
> default:
> pr_cont("Either hardware does not support performance "
> "counters, or not yet implemented.\n");
> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
> index 01eff7e..cd55823 100644
> --- a/arch/mips/kernel/traps.c
> +++ b/arch/mips/kernel/traps.c
> @@ -1241,6 +1241,7 @@ static inline void parity_protection_init(void)
> break;
>
> case CPU_5KC:
> + case CPU_LOONGSON1:
> write_c0_ecc(0x80000000);
> back_to_back_c0_hazard();
> /* Set the PE bit (bit 31) in the c0_errctl register. */
> diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson1/Kconfig
> new file mode 100644
> index 0000000..237fa21
> --- /dev/null
> +++ b/arch/mips/loongson1/Kconfig
> @@ -0,0 +1,21 @@
> +if MACH_LOONGSON1
> +
> +choice
> + prompt "Machine Type"
> +
> +config LOONGSON1_LS1B
> + bool "Loongson LS1B board"
> + select CEVT_R4K
> + select CSRC_R4K
> + select SYS_HAS_CPU_LOONGSON1B
> + select DMA_NONCOHERENT
> + select BOOT_ELF32
> + select IRQ_CPU
> + select SYS_SUPPORTS_32BIT_KERNEL
> + select SYS_SUPPORTS_LITTLE_ENDIAN
> + select SYS_SUPPORTS_HIGHMEM
> + select SYS_HAS_EARLY_PRINTK
> +
> +endchoice
> +
> +endif # MACH_LOONGSON1
> diff --git a/arch/mips/loongson1/Makefile b/arch/mips/loongson1/Makefile
> new file mode 100644
> index 0000000..e9123c2
> --- /dev/null
> +++ b/arch/mips/loongson1/Makefile
> @@ -0,0 +1,11 @@
> +#
> +# Common code for all Loongson1 based systems
> +#
> +
> +obj-$(CONFIG_MACH_LOONGSON1) += common/
> +
> +#
> +# Loongson LS1B board
> +#
> +
> +obj-$(CONFIG_LOONGSON1_LS1B) += ls1b/
> diff --git a/arch/mips/loongson1/Platform b/arch/mips/loongson1/Platform
> new file mode 100644
> index 0000000..92804c6
> --- /dev/null
> +++ b/arch/mips/loongson1/Platform
> @@ -0,0 +1,7 @@
> +cflags-$(CONFIG_CPU_LOONGSON1) += \
> + $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
> + -Wa,-mips32r2 -Wa,--trap
> +
> +platform-$(CONFIG_MACH_LOONGSON1) += loongson1/
> +cflags-$(CONFIG_MACH_LOONGSON1) += -I$(srctree)/arch/mips/include/asm/mach-loongson1
> +load-$(CONFIG_LOONGSON1_LS1B) += 0xffffffff80010000
> diff --git a/arch/mips/loongson1/common/Makefile b/arch/mips/loongson1/common/Makefile
> new file mode 100644
> index 0000000..b279770
> --- /dev/null
> +++ b/arch/mips/loongson1/common/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# Makefile for common code of loongson1 based machines.
> +#
> +
> +obj-y += clock.o irq.o platform.o prom.o reset.o setup.o
> diff --git a/arch/mips/loongson1/common/clock.c b/arch/mips/loongson1/common/clock.c
> new file mode 100644
> index 0000000..7f4f28b
> --- /dev/null
> +++ b/arch/mips/loongson1/common/clock.c
> @@ -0,0 +1,165 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/list.h>
> +#include <linux/mutex.h>
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <asm/clock.h>
> +#include <asm/time.h>
> +
> +#include <loongson1.h>
> +
> +static LIST_HEAD(clocks);
> +static DEFINE_MUTEX(clocks_mutex);
> +
> +struct clk *clk_get(struct device *dev, const char *name)
> +{
> + struct clk *c;
> + struct clk *ret = NULL;
> +
> + mutex_lock(&clocks_mutex);
> + list_for_each_entry(c, &clocks, node) {
> + if (!strcmp(c->name, name)) {
> + ret = c;
> + break;
> + }
> + }
> + mutex_unlock(&clocks_mutex);
> +
> + return ret;
> +}
> +EXPORT_SYMBOL(clk_get);
> +
> +unsigned long clk_get_rate(struct clk *clk)
> +{
> + return clk->rate;
> +}
> +EXPORT_SYMBOL(clk_get_rate);
> +
> +static void pll_clk_init(struct clk *clk)
> +{
> + u32 pll;
> +
> + pll = __raw_readl(LS1_CLK_PLL_FREQ);
> + clk->rate = (12 + (pll & 0x3f)) * 33 / 2
> + + ((pll >> 8) & 0x3ff) * 33 / 1024 / 2;
> + clk->rate *= 1000000;
> +}
> +
> +static void cpu_clk_init(struct clk *clk)
> +{
> + u32 pll, ctrl;
> +
> + pll = clk_get_rate(clk->parent);
> + ctrl = __raw_readl(LS1_CLK_PLL_DIV) & DIV_CPU;
> + clk->rate = pll / (ctrl >> DIV_CPU_SHIFT);
> +}
> +
> +static void ddr_clk_init(struct clk *clk)
> +{
> + u32 pll, ctrl;
> +
> + pll = clk_get_rate(clk->parent);
> + ctrl = __raw_readl(LS1_CLK_PLL_DIV) & DIV_DDR;
> + clk->rate = pll / (ctrl >> DIV_DDR_SHIFT);
> +}
> +
> +static void dc_clk_init(struct clk *clk)
> +{
> + u32 pll, ctrl;
> +
> + pll = clk_get_rate(clk->parent);
> + ctrl = __raw_readl(LS1_CLK_PLL_DIV) & DIV_DC;
> + clk->rate = pll / (ctrl >> DIV_DC_SHIFT);
> +}
> +
> +static struct clk_ops pll_clk_ops = {
> + .init = pll_clk_init,
> +};
> +
> +static struct clk_ops cpu_clk_ops = {
> + .init = cpu_clk_init,
> +};
> +
> +static struct clk_ops ddr_clk_ops = {
> + .init = ddr_clk_init,
> +};
> +
> +static struct clk_ops dc_clk_ops = {
> + .init = dc_clk_init,
> +};
> +
> +static struct clk pll_clk = {
> + .name = "pll",
> + .ops = &pll_clk_ops,
> +};
> +
> +static struct clk cpu_clk = {
> + .name = "cpu",
> + .parent = &pll_clk,
> + .ops = &cpu_clk_ops,
> +};
> +
> +static struct clk ddr_clk = {
> + .name = "ddr",
> + .parent = &pll_clk,
> + .ops = &ddr_clk_ops,
> +};
> +
> +static struct clk dc_clk = {
> + .name = "dc",
> + .parent = &pll_clk,
> + .ops = &dc_clk_ops,
> +};
> +
> +int clk_register(struct clk *clk)
> +{
> + mutex_lock(&clocks_mutex);
> + list_add(&clk->node, &clocks);
> + if (clk->ops->init)
> + clk->ops->init(clk);
> + mutex_unlock(&clocks_mutex);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(clk_register);
> +
> +static struct clk *loongson1_clks[] = {
> + &pll_clk,
> + &cpu_clk,
> + &ddr_clk,
> + &dc_clk,
> +};
> +
> +int __init loongson1_clock_init(void)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(loongson1_clks); i++)
> + clk_register(loongson1_clks[i]);
> +
> + return 0;
> +}
> +
> +void __init plat_time_init(void)
> +{
> + struct clk *clk;
> +
> + /* Initialize loongson1 clocks */
> + loongson1_clock_init();
> +
> + /* setup mips r4k timer */
> + clk = clk_get(NULL, "cpu");
> + if (IS_ERR(clk))
> + panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
> +
> + mips_hpt_frequency = clk_get_rate(clk) / 2;
> +}
> diff --git a/arch/mips/loongson1/common/irq.c b/arch/mips/loongson1/common/irq.c
> new file mode 100644
> index 0000000..a5dcabb
> --- /dev/null
> +++ b/arch/mips/loongson1/common/irq.c
> @@ -0,0 +1,136 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
> +#include <asm/irq_cpu.h>
> +
> +#include <loongson1.h>
> +#include <irq.h>
> +
> +static void loongson1_irq_ack(struct irq_data *d)
> +{
> + unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
> + unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
> +
> + __raw_writel(__raw_readl(LS1_INTC_INTCLR(n))
> + | (1 << bit), LS1_INTC_INTCLR(n));
> +}
> +
> +static void loongson1_irq_mask(struct irq_data *d)
> +{
> + unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
> + unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
> +
> + __raw_writel(__raw_readl(LS1_INTC_INTIEN(n))
> + & ~(1 << bit), LS1_INTC_INTIEN(n));
> +}
> +
> +static void loongson1_irq_mask_ack(struct irq_data *d)
> +{
> + unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
> + unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
> +
> + __raw_writel(__raw_readl(LS1_INTC_INTIEN(n))
> + & ~(1 << bit), LS1_INTC_INTIEN(n));
> + __raw_writel(__raw_readl(LS1_INTC_INTCLR(n))
> + | (1 << bit), LS1_INTC_INTCLR(n));
> +}
> +
> +static void loongson1_irq_unmask(struct irq_data *d)
> +{
> + unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
> + unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
> +
> + __raw_writel(__raw_readl(LS1_INTC_INTIEN(n))
> + | (1 << bit), LS1_INTC_INTIEN(n));
> +}
> +
> +static struct irq_chip loongson1_irq_chip = {
> + .name = "LOONGSON1-INTC",
> + .irq_ack = loongson1_irq_ack,
> + .irq_mask = loongson1_irq_mask,
> + .irq_mask_ack = loongson1_irq_mask_ack,
> + .irq_unmask = loongson1_irq_unmask,
> +};
> +
> +static void loongson1_irq_dispatch(int n)
> +{
> + u32 int_status, irq;
> +
> + /* Get pending sources, masked by current enables */
> + int_status = __raw_readl(LS1_INTC_INTISR(n)) &
> + __raw_readl(LS1_INTC_INTIEN(n));
> +
> + if (int_status) {
> + irq = LOONGSON1_IRQ(n, __ffs(int_status));
> + do_IRQ(irq);
> + }
> +}
> +
> +asmlinkage void plat_irq_dispatch(void)
> +{
> + unsigned int pending;
> +
> + pending = read_c0_cause() & read_c0_status() & ST0_IM;
> +
> + if (pending & CAUSEF_IP7)
> + do_IRQ(TIMER_IRQ);
> + else if (pending & CAUSEF_IP2)
> + loongson1_irq_dispatch(0); /* INT0 */
> + else if (pending & CAUSEF_IP3)
> + loongson1_irq_dispatch(1); /* INT1 */
> + else if (pending & CAUSEF_IP4)
> + loongson1_irq_dispatch(2); /* INT2 */
> + else if (pending & CAUSEF_IP5)
> + loongson1_irq_dispatch(3); /* INT3 */
> + else if (pending & CAUSEF_IP6)
> + loongson1_irq_dispatch(4); /* INT4 */
> + else
> + spurious_interrupt();
> +
> +}
> +
> +struct irqaction cascade_irqaction = {
> + .handler = no_action,
> + .name = "cascade",
> + .flags = IRQF_NO_THREAD,
> +};
> +
> +static void __init loongson1_irq_init(int base)
> +{
> + int n;
> +
> + /* Disable interrupts and clear pending,
> + * setup all IRQs as high level triggered
> + */
> + for (n = 0; n < 4; n++) {
> + __raw_writel(0x0, LS1_INTC_INTIEN(n));
> + __raw_writel(0xffffffff, LS1_INTC_INTCLR(n));
> + __raw_writel(0xffffffff, LS1_INTC_INTPOL(n));
> + __raw_writel(0x0, LS1_INTC_INTEDGE(n));
> + }
> +
> +
> + for (n = base; n < NR_IRQS; n++) {
> + irq_set_chip_and_handler(n, &loongson1_irq_chip,
> + handle_level_irq);
> + }
> +
> + setup_irq(INT0_IRQ, &cascade_irqaction);
> + setup_irq(INT1_IRQ, &cascade_irqaction);
> + setup_irq(INT2_IRQ, &cascade_irqaction);
> + setup_irq(INT3_IRQ, &cascade_irqaction);
> +}
> +
> +void __init arch_init_irq(void)
> +{
> + mips_cpu_irq_init();
> + loongson1_irq_init(LOONGSON1_IRQ_BASE);
> +}
> diff --git a/arch/mips/loongson1/common/platform.c b/arch/mips/loongson1/common/platform.c
> new file mode 100644
> index 0000000..c93028e
> --- /dev/null
> +++ b/arch/mips/loongson1/common/platform.c
> @@ -0,0 +1,50 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/err.h>
> +#include <linux/serial_8250.h>
> +
> +#include <loongson1.h>
> +
> +#define LOONGSON1_UART_PORT(_id) \
> + { \
> + .mapbase = LOONGSON1_UART ## _id ## _BASE, \
> + .membase = (void *)(LOONGSON1_UART ## _id ## _BASE), \
> + .irq = LOONGSON1_UART ## _id ## _IRQ, \
> + .iotype = UPIO_MEM, \
> + .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, \
> + .type = PORT_16550A, \
> + }
> +
> +static struct plat_serial8250_port loongson1_serial8250_port[] = {
> + LOONGSON1_UART_PORT(0),
> + {},
> +};
> +
> +struct platform_device loongson1_uart_device = {
> + .name = "serial8250",
> + .id = PLAT8250_DEV_PLATFORM,
> + .dev = {
> + .platform_data = loongson1_serial8250_port,
> + },
> +};
> +
> +void __init loongson1_serial_setup(void)
> +{
> + struct clk *clk;
> + struct plat_serial8250_port *p;
> +
> + clk = clk_get(NULL, "dc");
> + if (IS_ERR(clk))
> + panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
> +
> + for (p = loongson1_serial8250_port; p->flags != 0; ++p)
> + p->uartclk = clk_get_rate(clk);
> +}
> diff --git a/arch/mips/loongson1/common/prom.c b/arch/mips/loongson1/common/prom.c
> new file mode 100644
> index 0000000..70791f1
> --- /dev/null
> +++ b/arch/mips/loongson1/common/prom.c
> @@ -0,0 +1,88 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * Modified from arch/mips/pnx833x/common/prom.c.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#include <linux/serial_reg.h>
> +#include <asm/bootinfo.h>
> +
> +#include <loongson1.h>
> +#include <prom.h>
> +
> +int prom_argc;
> +char **prom_argv, **prom_envp;
> +unsigned long memsize, highmemsize;
> +
> +char *prom_getenv(char *envname)
> +{
> + char **env = prom_envp;
> + int i;
> +
> + i = strlen(envname);
> +
> + while (*env) {
> + if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=')
> + return *env + i + 1;
> + env++;
> + }
> +
> + return 0;
> +}
> +
> +static inline unsigned long env_or_default(char *env, unsigned long dfl)
> +{
> + char *str = prom_getenv(env);
> + return str ? simple_strtol(str, 0, 0) : dfl;
> +}
> +
> +void __init prom_init_cmdline(void)
> +{
> + char *c = &(arcs_cmdline[0]);
> + int i;
> +
> + for (i = 1; i < prom_argc; i++) {
> + strcpy(c, prom_argv[i]);
> + c += strlen(prom_argv[i]);
> + if (i < prom_argc-1)
> + *c++ = ' ';
> + }
> + *c = 0;
> +}
> +
> +void __init prom_init(void)
> +{
> + prom_argc = fw_arg0;
> + prom_argv = (char **)fw_arg1;
> + prom_envp = (char **)fw_arg2;
> +
> + prom_init_cmdline();
> +
> + memsize = env_or_default("memsize", DEFAULT_MEMSIZE);
> + highmemsize = env_or_default("highmemsize", 0x0);
> +}
> +
> +void __init prom_free_prom_memory(void)
> +{
> +}
> +
> +#define UART_BASE LOONGSON1_UART0_BASE
> +#define PORT(base, offset) (u8 *)(base + offset)
> +
> +void __init prom_putchar(char c)
> +{
> + int timeout;
> +
> + timeout = 1024;
> +
> + while (((readb(PORT(UART_BASE, UART_LSR)) & UART_LSR_THRE) == 0)
> + && (timeout-- > 0))
> + ;
> +
> + writeb(c, PORT(UART_BASE, UART_TX));
> +}
> diff --git a/arch/mips/loongson1/common/reset.c b/arch/mips/loongson1/common/reset.c
> new file mode 100644
> index 0000000..75f550f
> --- /dev/null
> +++ b/arch/mips/loongson1/common/reset.c
> @@ -0,0 +1,46 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#include <linux/io.h>
> +#include <linux/pm.h>
> +#include <asm/reboot.h>
> +
> +#include <loongson1.h>
> +
> +static void loongson1_restart(char *command)
> +{
> + __raw_writel(0x1, LS1_WDT_EN);
> + __raw_writel(0x5000000, LS1_WDT_TIMER);
> + __raw_writel(0x1, LS1_WDT_SET);
> +}
> +
> +static void loongson1_halt(void)
> +{
> + pr_notice("\n\n** You can safely turn off the power now **\n\n");
> + while (1) {
> + if (cpu_wait)
> + cpu_wait();
> + }
> +}
> +
> +static void loongson1_power_off(void)
> +{
> + loongson1_halt();
> +}
> +
> +static int __init loongson1_reboot_setup(void)
> +{
> + _machine_restart = loongson1_restart;
> + _machine_halt = loongson1_halt;
> + pm_power_off = loongson1_power_off;
> +
> + return 0;
> +}
> +
> +arch_initcall(loongson1_reboot_setup);
> diff --git a/arch/mips/loongson1/common/setup.c b/arch/mips/loongson1/common/setup.c
> new file mode 100644
> index 0000000..62128cc
> --- /dev/null
> +++ b/arch/mips/loongson1/common/setup.c
> @@ -0,0 +1,29 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#include <asm/bootinfo.h>
> +
> +#include <prom.h>
> +
> +void __init plat_mem_setup(void)
> +{
> + add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
> +}
> +
> +const char *get_system_type(void)
> +{
> + unsigned int processor_id = (¤t_cpu_data)->processor_id;
> +
> + switch (processor_id & PRID_REV_MASK) {
> + case PRID_REV_LOONGSON1B:
> + return "LOONGSON LS1B";
> + default:
> + return "LOONGSON (unknown)";
> + }
> +}
> diff --git a/arch/mips/loongson1/ls1b/Makefile b/arch/mips/loongson1/ls1b/Makefile
> new file mode 100644
> index 0000000..891eac4
> --- /dev/null
> +++ b/arch/mips/loongson1/ls1b/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# Makefile for loongson1B based machines.
> +#
> +
> +obj-y += board.o
> diff --git a/arch/mips/loongson1/ls1b/board.c b/arch/mips/loongson1/ls1b/board.c
> new file mode 100644
> index 0000000..b1a602f
> --- /dev/null
> +++ b/arch/mips/loongson1/ls1b/board.c
> @@ -0,0 +1,30 @@
> +/*
> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#include <platform.h>
> +
> +#include <linux/serial_8250.h>
> +#include <loongson1.h>
> +
> +static struct platform_device *loongson1_platform_devices[] __initdata = {
> + &loongson1_uart_device,
> +};
> +
> +static int __init loongson1_platform_init(void)
> +{
> + int err;
> +
> + loongson1_serial_setup();
> +
> + err = platform_add_devices(loongson1_platform_devices,
> + ARRAY_SIZE(loongson1_platform_devices));
> + return err;
> +}
> +
> +arch_initcall(loongson1_platform_init);
> diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
> index d1f2d4c..99216f0 100644
> --- a/arch/mips/oprofile/common.c
> +++ b/arch/mips/oprofile/common.c
> @@ -89,6 +89,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
> case CPU_R10000:
> case CPU_R12000:
> case CPU_R14000:
> + case CPU_LOONGSON1:
> lmodel = &op_model_mipsxx_ops;
> break;
>
> diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
> index 54759f1..03be670 100644
> --- a/arch/mips/oprofile/op_model_mipsxx.c
> +++ b/arch/mips/oprofile/op_model_mipsxx.c
> @@ -365,6 +365,10 @@ static int __init mipsxx_init(void)
> op_model_mipsxx_ops.cpu_type = "mips/sb1";
> break;
>
> + case CPU_LOONGSON1:
> + op_model_mipsxx_ops.cpu_type = "mips/loongson1";
> + break;
> +
> default:
> printk(KERN_ERR "Profiling unsupported for this CPU\n");
Regards,
Wu Zhangjin
>
> --
> 1.7.4.1
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 1/2] MIPS: Add basic support for Loongson1B (UPDATED)
2011-09-25 5:27 ` wu zhangjin
@ 2011-09-25 13:40 ` Shane McDonald
2011-09-26 1:40 ` wu zhangjin
2011-09-26 9:00 ` Kelvin Cheung
1 sibling, 1 reply; 8+ messages in thread
From: Shane McDonald @ 2011-09-25 13:40 UTC (permalink / raw)
To: wu zhangjin; +Cc: keguang.zhang, linux-mips, linux-kernel, ralf, r0bertz, chenj
>> diff --git a/arch/mips/include/asm/mach-loongson1/regs-clk.h b/arch/mips/include/asm/mach-loongson1/regs-clk.h
>> new file mode 100644
>> index 0000000..7a09d6a
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-loongson1/regs-clk.h
>> @@ -0,0 +1,32 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * Loongson1 Clock Register Definitions.
>> + *
>> + * This program is free software; you can redistribute it and/or modify it
>> + * under the terms of the GNU General Public License as published by the
>> + * Free Software Foundation; either version 2 of the License, or (at your
>> + * option) any later version.
>> + */
>> +
>> +#ifndef __ASM_MACH_LOONGSON1_REGS_CLK_H
>> +#define __ASM_MACH_LOONGSON1_REGS_CLK_H
>> +
>> +#define LS1_CLK_REG(x) ((void __iomem *)(LOONGSON1_CLK_BASE + (x)))
>
> "volatile" keyword may be required for __iomem access, the same to the
> following similar usage.
>
> Considering a scene is(LS1_XXX_REG(X) doesn't really exist):
>
> LS1_XXX_REG(X) = 0; /* put cpu into idle and wait interrupt */
> LS1_XXX_REG(X) = 7; /* recover the cpu frequency to the highest */
>
> If no "volatile" keyword indicated, the above two lines will be
> intelligently but wrongly removed by compiler.
No -- please see Documentation/volatile-considered-harmful.txt,
particularly the paragraph starting at line 49. This macro
is only being used as an argument to __raw_readl,
as it should be.
Shane
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] MIPS: Add basic support for Loongson1B (UPDATED)
2011-09-25 13:40 ` Shane McDonald
@ 2011-09-26 1:40 ` wu zhangjin
2011-09-26 9:01 ` Kelvin Cheung
0 siblings, 1 reply; 8+ messages in thread
From: wu zhangjin @ 2011-09-26 1:40 UTC (permalink / raw)
To: Shane McDonald
Cc: keguang.zhang, linux-mips, linux-kernel, ralf, r0bertz, chenj
On Sun, Sep 25, 2011 at 9:40 PM, Shane McDonald
<mcdonald.shane@gmail.com> wrote:
>>> diff --git a/arch/mips/include/asm/mach-loongson1/regs-clk.h b/arch/mips/include/asm/mach-loongson1/regs-clk.h
>>> new file mode 100644
>>> index 0000000..7a09d6a
>>> --- /dev/null
>>> +++ b/arch/mips/include/asm/mach-loongson1/regs-clk.h
>>> @@ -0,0 +1,32 @@
>>> +/*
>>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>>> + *
>>> + * Loongson1 Clock Register Definitions.
>>> + *
>>> + * This program is free software; you can redistribute it and/or modify it
>>> + * under the terms of the GNU General Public License as published by the
>>> + * Free Software Foundation; either version 2 of the License, or (at your
>>> + * option) any later version.
>>> + */
>>> +
>>> +#ifndef __ASM_MACH_LOONGSON1_REGS_CLK_H
>>> +#define __ASM_MACH_LOONGSON1_REGS_CLK_H
>>> +
>>> +#define LS1_CLK_REG(x) ((void __iomem *)(LOONGSON1_CLK_BASE + (x)))
>>
>> "volatile" keyword may be required for __iomem access, the same to the
>> following similar usage.
>>
>> Considering a scene is(LS1_XXX_REG(X) doesn't really exist):
>>
>> LS1_XXX_REG(X) = 0; /* put cpu into idle and wait interrupt */
>> LS1_XXX_REG(X) = 7; /* recover the cpu frequency to the highest */
>>
>> If no "volatile" keyword indicated, the first line will be
>> intelligently but wrongly removed by compiler.
>
> No -- please see Documentation/volatile-considered-harmful.txt,
> particularly the paragraph starting at line 49. This macro
> is only being used as an argument to __raw_readl,
> as it should be.
Yeah, __raw_readl/writel() will use volatile to prevent it from
optimization, thanks ;)
"within the kernel, I/O memory accesses are always done through
accessor functions;
accessing I/O memory directly through pointers is frowned upon and
does not work on all
architectures. Those accessors are written to prevent unwanted
optimization,
....
- The above-mentioned accessor functions might use volatile on
architectures where direct I/O memory access does work. Essentially,
each accessor call becomes a little critical section on its own and
ensures that the access happens as expected by the programmer.
...
Patches to remove volatile variables are generally welcome - as long as
they come with a justification which shows that the concurrency issues have
been properly thought through.
"
Thanks & Regards,
Wu Zhangjin
>
> Shane
>
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 1/2] MIPS: Add basic support for Loongson1B (UPDATED)
2011-09-26 1:40 ` wu zhangjin
@ 2011-09-26 9:01 ` Kelvin Cheung
0 siblings, 0 replies; 8+ messages in thread
From: Kelvin Cheung @ 2011-09-26 9:01 UTC (permalink / raw)
To: wu zhangjin
Cc: Shane McDonald, linux-mips, linux-kernel, ralf, r0bertz, chenj
I have noticed this.
And all register accesses in my patch are done through __raw_readl/__raw_writel.
2011/9/26, wu zhangjin <wuzhangjin@gmail.com>:
> On Sun, Sep 25, 2011 at 9:40 PM, Shane McDonald
> <mcdonald.shane@gmail.com> wrote:
>>>> diff --git a/arch/mips/include/asm/mach-loongson1/regs-clk.h
>>>> b/arch/mips/include/asm/mach-loongson1/regs-clk.h
>>>> new file mode 100644
>>>> index 0000000..7a09d6a
>>>> --- /dev/null
>>>> +++ b/arch/mips/include/asm/mach-loongson1/regs-clk.h
>>>> @@ -0,0 +1,32 @@
>>>> +/*
>>>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>>>> + *
>>>> + * Loongson1 Clock Register Definitions.
>>>> + *
>>>> + * This program is free software; you can redistribute it and/or
>>>> modify it
>>>> + * under the terms of the GNU General Public License as published by
>>>> the
>>>> + * Free Software Foundation; either version 2 of the License, or (at
>>>> your
>>>> + * option) any later version.
>>>> + */
>>>> +
>>>> +#ifndef __ASM_MACH_LOONGSON1_REGS_CLK_H
>>>> +#define __ASM_MACH_LOONGSON1_REGS_CLK_H
>>>> +
>>>> +#define LS1_CLK_REG(x) ((void __iomem *)(LOONGSON1_CLK_BASE +
>>>> (x)))
>>>
>>> "volatile" keyword may be required for __iomem access, the same to the
>>> following similar usage.
>>>
>>> Considering a scene is(LS1_XXX_REG(X) doesn't really exist):
>>>
>>> LS1_XXX_REG(X) = 0; /* put cpu into idle and wait interrupt
>>> */
>>> LS1_XXX_REG(X) = 7; /* recover the cpu frequency to the
>>> highest */
>>>
>>> If no "volatile" keyword indicated, the first line will be
>>> intelligently but wrongly removed by compiler.
>>
>> No -- please see Documentation/volatile-considered-harmful.txt,
>> particularly the paragraph starting at line 49. This macro
>> is only being used as an argument to __raw_readl,
>> as it should be.
>
> Yeah, __raw_readl/writel() will use volatile to prevent it from
> optimization, thanks ;)
>
> "within the kernel, I/O memory accesses are always done through
> accessor functions;
> accessing I/O memory directly through pointers is frowned upon and
> does not work on all
> architectures. Those accessors are written to prevent unwanted
> optimization,
> ....
> - The above-mentioned accessor functions might use volatile on
> architectures where direct I/O memory access does work. Essentially,
> each accessor call becomes a little critical section on its own and
> ensures that the access happens as expected by the programmer.
> ...
> Patches to remove volatile variables are generally welcome - as long as
> they come with a justification which shows that the concurrency issues have
> been properly thought through.
> "
>
> Thanks & Regards,
> Wu Zhangjin
>
>>
>> Shane
>>
>
--
Best Regards!
Kelvin
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] MIPS: Add basic support for Loongson1B (UPDATED)
2011-09-25 5:27 ` wu zhangjin
2011-09-25 13:40 ` Shane McDonald
@ 2011-09-26 9:00 ` Kelvin Cheung
1 sibling, 0 replies; 8+ messages in thread
From: Kelvin Cheung @ 2011-09-26 9:00 UTC (permalink / raw)
To: wu zhangjin; +Cc: linux-mips, linux-kernel, ralf, r0bertz, chenj
2011/9/25, wu zhangjin <wuzhangjin@gmail.com>:
> On Sat, Sep 24, 2011 at 2:21 PM, <keguang.zhang@gmail.com> wrote:
>> From: Kelvin Cheung <keguang.zhang@gmail.com>
>>
>> This patch adds basic support for Loongson1B
>> including serial port, timer and interrupt handler.
>>
>> Loongson 1B is a 32-bit SoC designed by Institute of
>> Computing Technology (ICT), Chinese Academy of Sciences (CAS),
>> which implements the MIPS32 release 2 instruction set.
>>
>> Signed-off-by: Kelvin Cheung <keguang.zhang@gmail.com>
>> ---
>> arch/mips/Kbuild.platforms | 1 +
>> arch/mips/Kconfig | 31 ++++
>> arch/mips/include/asm/cpu.h | 3 +-
>> arch/mips/include/asm/mach-loongson1/irq.h | 70 +++++++++
>> arch/mips/include/asm/mach-loongson1/loongson1.h | 48 +++++++
>> arch/mips/include/asm/mach-loongson1/platform.h | 20 +++
>> arch/mips/include/asm/mach-loongson1/prom.h | 24 +++
>> arch/mips/include/asm/mach-loongson1/regs-clk.h | 32 ++++
>> arch/mips/include/asm/mach-loongson1/regs-intc.h | 25 ++++
>> arch/mips/include/asm/mach-loongson1/regs-wdt.h | 21 +++
>> arch/mips/include/asm/mach-loongson1/war.h | 25 ++++
>> arch/mips/include/asm/module.h | 2 +
>> arch/mips/kernel/cpu-probe.c | 15 ++
>> arch/mips/kernel/perf_event_mipsxx.c | 6 +
>> arch/mips/kernel/traps.c | 1 +
>> arch/mips/loongson1/Kconfig | 21 +++
>> arch/mips/loongson1/Makefile | 11 ++
>> arch/mips/loongson1/Platform | 7 +
>> arch/mips/loongson1/common/Makefile | 5 +
>> arch/mips/loongson1/common/clock.c | 165
>> ++++++++++++++++++++++
>> arch/mips/loongson1/common/irq.c | 136
>> ++++++++++++++++++
>> arch/mips/loongson1/common/platform.c | 50 +++++++
>> arch/mips/loongson1/common/prom.c | 88 ++++++++++++
>> arch/mips/loongson1/common/reset.c | 46 ++++++
>> arch/mips/loongson1/common/setup.c | 29 ++++
>> arch/mips/loongson1/ls1b/Makefile | 5 +
>> arch/mips/loongson1/ls1b/board.c | 30 ++++
>> arch/mips/oprofile/common.c | 1 +
>> arch/mips/oprofile/op_model_mipsxx.c | 4 +
>> 29 files changed, 921 insertions(+), 1 deletions(-)
>> create mode 100644 arch/mips/include/asm/mach-loongson1/irq.h
>> create mode 100644 arch/mips/include/asm/mach-loongson1/loongson1.h
>> create mode 100644 arch/mips/include/asm/mach-loongson1/platform.h
>> create mode 100644 arch/mips/include/asm/mach-loongson1/prom.h
>> create mode 100644 arch/mips/include/asm/mach-loongson1/regs-clk.h
>> create mode 100644 arch/mips/include/asm/mach-loongson1/regs-intc.h
>> create mode 100644 arch/mips/include/asm/mach-loongson1/regs-wdt.h
>> create mode 100644 arch/mips/include/asm/mach-loongson1/war.h
>> create mode 100644 arch/mips/loongson1/Kconfig
>> create mode 100644 arch/mips/loongson1/Makefile
>> create mode 100644 arch/mips/loongson1/Platform
>> create mode 100644 arch/mips/loongson1/common/Makefile
>> create mode 100644 arch/mips/loongson1/common/clock.c
>> create mode 100644 arch/mips/loongson1/common/irq.c
>> create mode 100644 arch/mips/loongson1/common/platform.c
>> create mode 100644 arch/mips/loongson1/common/prom.c
>> create mode 100644 arch/mips/loongson1/common/reset.c
>> create mode 100644 arch/mips/loongson1/common/setup.c
>> create mode 100644 arch/mips/loongson1/ls1b/Makefile
>> create mode 100644 arch/mips/loongson1/ls1b/board.c
>>
>> diff --git a/arch/mips/Kbuild.platforms b/arch/mips/Kbuild.platforms
>> index 5ce8029..d64786d 100644
>> --- a/arch/mips/Kbuild.platforms
>> +++ b/arch/mips/Kbuild.platforms
>> @@ -14,6 +14,7 @@ platforms += jz4740
>> platforms += lantiq
>> platforms += lasat
>> platforms += loongson
>> +platforms += loongson1
>> platforms += mipssim
>> platforms += mti-malta
>> platforms += netlogic
>> diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
>> index d9b8ea8..4c6ad4f 100644
>> --- a/arch/mips/Kconfig
>> +++ b/arch/mips/Kconfig
>> @@ -262,6 +262,17 @@ config MACH_LOONGSON
>> Chinese Academy of Sciences (CAS) in the People's Republic
>> of China. The chief architect is Professor Weiwu Hu.
>>
>> +config MACH_LOONGSON1
>> + bool "Loongson1 family of machines"
>> + select SYS_SUPPORTS_ZBOOT
>> + help
>> + This enables the support of Loongson1 family of machines.
>> +
>> + Loongson1 is a family of 32-bit MIPS-compatible SoCs.
>> + developed at Institute of Computing Technology (ICT),
>> + Chinese Academy of Sciences (CAS) in the People's Republic
>> + of China.
>> +
>> config MIPS_MALTA
>> bool "MIPS Malta board"
>> select ARCH_MAY_HAVE_PC_FDC
>> @@ -808,6 +819,7 @@ source "arch/mips/txx9/Kconfig"
>> source "arch/mips/vr41xx/Kconfig"
>> source "arch/mips/cavium-octeon/Kconfig"
>> source "arch/mips/loongson/Kconfig"
>> +source "arch/mips/loongson1/Kconfig"
>> source "arch/mips/netlogic/Kconfig"
>>
>> endmenu
>> @@ -1201,6 +1213,14 @@ config CPU_LOONGSON2F
>> have a similar programming interface with FPGA northbridge used
>> in
>> Loongson2E.
>>
>> +config CPU_LOONGSON1B
>> + bool "Loongson 1B"
>> + depends on SYS_HAS_CPU_LOONGSON1B
>> + select CPU_LOONGSON1
>> + help
>> + The Loongson 1B is a 32-bit SoC, which implements the MIPS32
>> + release 2 instruction set.
>> +
>> config CPU_MIPS32_R1
>> bool "MIPS32 Release 1"
>> depends on SYS_HAS_CPU_MIPS32_R1
>> @@ -1529,6 +1549,14 @@ config CPU_LOONGSON2
>> select CPU_SUPPORTS_64BIT_KERNEL
>> select CPU_SUPPORTS_HIGHMEM
>>
>> +config CPU_LOONGSON1
>> + bool
>> + select CPU_MIPS32
>> + select CPU_MIPSR2
>> + select CPU_HAS_PREFETCH
>> + select CPU_SUPPORTS_32BIT_KERNEL
>> + select CPU_SUPPORTS_HIGHMEM
>> +
>> config SYS_HAS_CPU_LOONGSON2E
>> bool
>>
>> @@ -1538,6 +1566,9 @@ config SYS_HAS_CPU_LOONGSON2F
>> select CPU_SUPPORTS_ADDRWINCFG if 64BIT
>> select CPU_SUPPORTS_UNCACHED_ACCELERATED
>>
>> +config SYS_HAS_CPU_LOONGSON1B
>> + bool
>> +
>> config SYS_HAS_CPU_MIPS32_R1
>> bool
>>
>> diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
>> index 5f95a4b..975f372 100644
>> --- a/arch/mips/include/asm/cpu.h
>> +++ b/arch/mips/include/asm/cpu.h
>> @@ -191,6 +191,7 @@
>> #define PRID_REV_34K_V1_0_2 0x0022
>> #define PRID_REV_LOONGSON2E 0x0002
>> #define PRID_REV_LOONGSON2F 0x0003
>> +#define PRID_REV_LOONGSON1B 0x0020
>>
>> /*
>> * Older processors used to encode processor version and revision in two
>> @@ -253,7 +254,7 @@ enum cpu_type_enum {
>> */
>> CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
>> CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
>> - CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC,
>> + CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1,
>>
>> /*
>> * MIPS64 class processors
>> diff --git a/arch/mips/include/asm/mach-loongson1/irq.h
>> b/arch/mips/include/asm/mach-loongson1/irq.h
>> new file mode 100644
>> index 0000000..e8fed7a
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-loongson1/irq.h
>> @@ -0,0 +1,70 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * IRQ mappings for Loongson1.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +
>> +#ifndef __ASM_MACH_LOONGSON1_IRQ_H
>> +#define __ASM_MACH_LOONGSON1_IRQ_H
>> +
>> +/*
>> + * CPU core Interrupt Numbers
>> + */
>> +#define MIPS_CPU_IRQ_BASE 0
>> +#define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x))
>> +#define SOFTINT0_IRQ MIPS_CPU_IRQ(0)
>> +#define SOFTINT1_IRQ MIPS_CPU_IRQ(1)
>> +#define INT0_IRQ MIPS_CPU_IRQ(2)
>> +#define INT1_IRQ MIPS_CPU_IRQ(3)
>> +#define INT2_IRQ MIPS_CPU_IRQ(4)
>> +#define INT3_IRQ MIPS_CPU_IRQ(5)
>> +#define INT4_IRQ MIPS_CPU_IRQ(6)
>> +#define TIMER_IRQ MIPS_CPU_IRQ(7) /* cpu
>> timer */
>> +
>> +/*
>> + * INT0~3 Interrupt Numbers
>> + */
>> +#define LOONGSON1_IRQ_BASE 8
>> +#define LOONGSON1_IRQ(n, x) (LOONGSON1_IRQ_BASE + (n << 5) +
>> (x))
>> +
>> +#define LOONGSON1_UART0_IRQ LOONGSON1_IRQ(0, 2)
>> +#define LOONGSON1_UART1_IRQ LOONGSON1_IRQ(0, 3)
>> +#define LOONGSON1_UART2_IRQ LOONGSON1_IRQ(0, 4)
>> +#define LOONGSON1_UART3_IRQ LOONGSON1_IRQ(0, 5)
>> +#define LOONGSON1_CAN0_IRQ LOONGSON1_IRQ(0, 6)
>> +#define LOONGSON1_CAN1_IRQ LOONGSON1_IRQ(0, 7)
>> +#define LOONGSON1_SPI0_IRQ LOONGSON1_IRQ(0, 8)
>> +#define LOONGSON1_SPI1_IRQ LOONGSON1_IRQ(0, 9)
>> +#define LOONGSON1_AC97_IRQ LOONGSON1_IRQ(0, 10)
>> +#define LOONGSON1_DMA0_IRQ LOONGSON1_IRQ(0, 13)
>> +#define LOONGSON1_DMA1_IRQ LOONGSON1_IRQ(0, 14)
>> +#define LOONGSON1_DMA2_IRQ LOONGSON1_IRQ(0, 15)
>> +#define LOONGSON1_PWM0_IRQ LOONGSON1_IRQ(0, 17)
>> +#define LOONGSON1_PWM1_IRQ LOONGSON1_IRQ(0, 18)
>> +#define LOONGSON1_PWM2_IRQ LOONGSON1_IRQ(0, 19)
>> +#define LOONGSON1_PWM3_IRQ LOONGSON1_IRQ(0, 20)
>> +#define LOONGSON1_RTC_INT0_IRQ LOONGSON1_IRQ(0, 21)
>> +#define LOONGSON1_RTC_INT1_IRQ LOONGSON1_IRQ(0, 22)
>> +#define LOONGSON1_RTC_INT2_IRQ LOONGSON1_IRQ(0, 23)
>> +#define LOONGSON1_TOY_INT0_IRQ LOONGSON1_IRQ(0, 24)
>> +#define LOONGSON1_TOY_INT1_IRQ LOONGSON1_IRQ(0, 25)
>> +#define LOONGSON1_TOY_INT2_IRQ LOONGSON1_IRQ(0, 26)
>> +#define LOONGSON1_RTC_TICK_IRQ LOONGSON1_IRQ(0, 27)
>> +#define LOONGSON1_TOY_TICK_IRQ LOONGSON1_IRQ(0, 28)
>> +#define LOONGSON1_UART4_IRQ LOONGSON1_IRQ(0, 29)
>> +#define LOONGSON1_UART5_IRQ LOONGSON1_IRQ(0, 30)
>> +
>> +#define LOONGSON1_OHCI_IRQ LOONGSON1_IRQ(1, 0)
>> +#define LOONGSON1_EHCI_IRQ LOONGSON1_IRQ(1, 1)
>> +#define LOONGSON1_GMAC0_IRQ LOONGSON1_IRQ(1, 2)
>> +#define LOONGSON1_GMAC1_IRQ LOONGSON1_IRQ(1, 3)
>> +
>> +#define NR_IRQS LOONGSON1_GMAC1_IRQ
>
> Are you using TAB above?
Yes.
The mail did not show it correctly.
>> +
>> +#endif /* __ASM_MACH_LOONGSON1_IRQ_H */
>> diff --git a/arch/mips/include/asm/mach-loongson1/loongson1.h
>> b/arch/mips/include/asm/mach-loongson1/loongson1.h
>> new file mode 100644
>> index 0000000..466136d
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-loongson1/loongson1.h
>> @@ -0,0 +1,48 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * Register mappings for Loongson1.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +
>> +#ifndef __ASM_MACH_LOONGSON1_LOONGSON1_H
>> +#define __ASM_MACH_LOONGSON1_LOONGSON1_H
>> +
>> +#define DEFAULT_MEMSIZE (256) /* If no memsize
>> provided */
>> +
>> +/* Loongson1 Register Bases */
>> +/* All regs are accessed in KSEG1 */
>> +#define LOONGSON1_REGBASE (0xa0000000ul + 0x1fe00000ul)
>> +
>> +#define LOONGSON1_INTC_BASE (0xbfd01040)
>> +#define LOONGSON1_USB_BASE (0xbfe00000)
>> +#define LOONGSON1_GMAC0_BASE (0xbfe10000)
>> +#define LOONGSON1_GMAC1_BASE (0xbfe20000)
>> +#define LOONGSON1_UART0_BASE (0xbfe40000)
>> +#define LOONGSON1_UART1_BASE (0xbfe44000)
>> +#define LOONGSON1_UART2_BASE (0xbfe48000)
>> +#define LOONGSON1_UART3_BASE (0xbfe4c000)
>> +#define LOONGSON1_UART4_BASE (0xbfe6c000)
>> +#define LOONGSON1_UART5_BASE (0xbfe7c000)
>> +#define LOONGSON1_CAN0_BASE (0xbfe50000)
>> +#define LOONGSON1_CAN1_BASE (0xbfe54000)
>> +#define LOONGSON1_I2C0_BASE (0xbfe58000)
>> +#define LOONGSON1_I2C1_BASE (0xbfe68000)
>> +#define LOONGSON1_I2C2_BASE (0xbfe70000)
>> +#define LOONGSON1_PWM_BASE (0xbfe5c000)
>> +#define LOONGSON1_WDT_BASE (0xbfe5c060)
>> +#define LOONGSON1_RTC_BASE (0xbfe64000)
>> +#define LOONGSON1_AC97_BASE (0xbfe74000)
>> +#define LOONGSON1_NAND_BASE (0xbfe78000)
>> +#define LOONGSON1_CLK_BASE (0xbfe78030)
>> +
>> +#include <regs-clk.h>
>> +#include <regs-intc.h>
>> +#include <regs-wdt.h>
>> +
>> +#endif /* __ASM_MACH_LOONGSON1_LOONGSON1_H */
>> diff --git a/arch/mips/include/asm/mach-loongson1/platform.h
>> b/arch/mips/include/asm/mach-loongson1/platform.h
>> new file mode 100644
>> index 0000000..db4f02e
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-loongson1/platform.h
>> @@ -0,0 +1,20 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +
>> +#ifndef __ASM_MACH_LOONGSON1_PLATFORM_H
>> +#define __ASM_MACH_LOONGSON1_PLATFORM_H
>> +
>> +#include <linux/platform_device.h>
>> +
>> +extern struct platform_device loongson1_uart_device;
>> +
>> +void loongson1_serial_setup(void);
>> +
>> +#endif /* __ASM_MACH_LOONGSON1_PLATFORM_H */
>> diff --git a/arch/mips/include/asm/mach-loongson1/prom.h
>> b/arch/mips/include/asm/mach-loongson1/prom.h
>> new file mode 100644
>> index 0000000..b871dc4
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-loongson1/prom.h
>> @@ -0,0 +1,24 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +#ifndef __ASM_MACH_LOONGSON1_PROM_H
>> +#define __ASM_MACH_LOONGSON1_PROM_H
>> +
>> +#include <linux/io.h>
>> +#include <linux/init.h>
>> +#include <linux/irq.h>
>> +
>> +/* environment arguments from bootloader */
>> +extern unsigned long memsize, highmemsize;
>> +
>> +/* loongson-specific command line, env and memory initialization */
>> +extern char *prom_getenv(char *name);
>> +extern void __init prom_init_cmdline(void);
>> +
>> +#endif /* __ASM_MACH_LOONGSON1_PROM_H */
>> diff --git a/arch/mips/include/asm/mach-loongson1/regs-clk.h
>> b/arch/mips/include/asm/mach-loongson1/regs-clk.h
>> new file mode 100644
>> index 0000000..7a09d6a
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-loongson1/regs-clk.h
>> @@ -0,0 +1,32 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * Loongson1 Clock Register Definitions.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +#ifndef __ASM_MACH_LOONGSON1_REGS_CLK_H
>> +#define __ASM_MACH_LOONGSON1_REGS_CLK_H
>> +
>> +#define LS1_CLK_REG(x) ((void __iomem *)(LOONGSON1_CLK_BASE +
>> (x)))
>
> "volatile" keyword may be required for __iomem access, the same to the
> following similar usage.
>
> Considering a scene is(LS1_XXX_REG(X) doesn't really exist):
>
> LS1_XXX_REG(X) = 0; /* put cpu into idle and wait interrupt */
> LS1_XXX_REG(X) = 7; /* recover the cpu frequency to the highest
> */
>
> If no "volatile" keyword indicated, the above two lines will be
> intelligently but wrongly removed by compiler.
>
>> +
>> +#define LS1_CLK_PLL_FREQ LS1_CLK_REG(0x0)
>> +#define LS1_CLK_PLL_DIV LS1_CLK_REG(0x4)
>> +
>> +/* Clock PLL Divisor Register Bits */
>> +#define DIV_DC_EN (0x1 << 31)
>> +#define DIV_DC (0x1f << 26)
>> +#define DIV_CPU_EN (0x1 << 25)
>> +#define DIV_CPU (0x1f << 20)
>> +#define DIV_DDR_EN (0x1 << 19)
>> +#define DIV_DDR (0x1f << 14)
>
> The above exist format violation, SPACE, TAB?
Fixed in the new patch.
>> +
>> +#define DIV_DC_SHIFT (26)
>> +#define DIV_CPU_SHIFT (20)
>> +#define DIV_DDR_SHIFT (14)
>
> parenthesis may be not required for the scenes.
Fixed in the new patch.
>> +
>> +#endif /* __ASM_MACH_LOONGSON1_REGS_CLK_H */
>> diff --git a/arch/mips/include/asm/mach-loongson1/regs-intc.h
>> b/arch/mips/include/asm/mach-loongson1/regs-intc.h
>> new file mode 100644
>> index 0000000..3c62411
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-loongson1/regs-intc.h
>> @@ -0,0 +1,25 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * Loongson1 Interrupt register definitions.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +#ifndef __ASM_MACH_LOONGSON1_REGS_INTC_H
>> +#define __ASM_MACH_LOONGSON1_REGS_INTC_H
>> +
>> +#define LS1_INTC_REG(x) ((void __iomem
>> *)(LOONGSON1_INTC_BASE \
>> + + n * 0x18 + x))
>
>
> This may be better:
>
> #define LS1_INTC_REG(x) \
> ((volatile void __iomem *)(LOONGSON1_INTC_BASE + (n * 0x18) + x))
Fixed in the new patch.
>> +
>> +#define LS1_INTC_INTISR(n) LS1_INTC_REG(0x0)
>> +#define LS1_INTC_INTIEN(n) LS1_INTC_REG(0x4)
>> +#define LS1_INTC_INTSET(n) LS1_INTC_REG(0x8)
>> +#define LS1_INTC_INTCLR(n) LS1_INTC_REG(0xc)
>> +#define LS1_INTC_INTPOL(n) LS1_INTC_REG(0x10)
>> +#define LS1_INTC_INTEDGE(n) LS1_INTC_REG(0x14)
>> +
>> +#endif /* __ASM_MACH_LOONGSON1_REGS_INTC_H */
>> diff --git a/arch/mips/include/asm/mach-loongson1/regs-wdt.h
>> b/arch/mips/include/asm/mach-loongson1/regs-wdt.h
>> new file mode 100644
>> index 0000000..2393dd7
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-loongson1/regs-wdt.h
>> @@ -0,0 +1,21 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * Loongson1 Watchdog register definitions.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +#ifndef __ASM_MACH_LOONGSON1_REGS_WDT_H
>> +#define __ASM_MACH_LOONGSON1_REGS_WDT_H
>> +
>> +#define LS1_WDT_REG(x) ((void __iomem *)(LOONGSON1_WDT_BASE +
>> (x)))
>> +
>> +#define LS1_WDT_EN LS1_WDT_REG(0x0)
>> +#define LS1_WDT_SET LS1_WDT_REG(0x4)
>> +#define LS1_WDT_TIMER LS1_WDT_REG(0x8)
>> +
>> +#endif /* __ASM_MACH_LOONGSON1_REGS_WDT_H */
>> diff --git a/arch/mips/include/asm/mach-loongson1/war.h
>> b/arch/mips/include/asm/mach-loongson1/war.h
>> new file mode 100644
>> index 0000000..e3680a8
>> --- /dev/null
>> +++ b/arch/mips/include/asm/mach-loongson1/war.h
>> @@ -0,0 +1,25 @@
>> +/*
>> + * This file is subject to the terms and conditions of the GNU General
>> Public
>> + * License. See the file "COPYING" in the main directory of this archive
>> + * for more details.
>> + *
>> + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle <ralf@linux-mips.org>
>> + */
>> +#ifndef __ASM_MACH_LOONGSON1_WAR_H
>> +#define __ASM_MACH_LOONGSON1_WAR_H
>> +
>> +#define R4600_V1_INDEX_ICACHEOP_WAR 0
>> +#define R4600_V1_HIT_CACHEOP_WAR 0
>> +#define R4600_V2_HIT_CACHEOP_WAR 0
>> +#define R5432_CP0_INTERRUPT_WAR 0
>> +#define BCM1250_M3_WAR 0
>> +#define SIBYTE_1956_WAR 0
>> +#define MIPS4K_ICACHE_REFILL_WAR 0
>> +#define MIPS_CACHE_SYNC_WAR 0
>> +#define TX49XX_ICACHE_INDEX_INV_WAR 0
>> +#define RM9000_CDEX_SMP_WAR 0
>> +#define ICACHE_REFILLS_WORKAROUND_WAR 0
>> +#define R10000_LLSC_WAR 0
>> +#define MIPS34K_MISSED_ITLB_WAR 0
>> +
>> +#endif /* __ASM_MACH_LOONGSON1_WAR_H */
>> diff --git a/arch/mips/include/asm/module.h
>> b/arch/mips/include/asm/module.h
>> index bc01a02..b53d642 100644
>> --- a/arch/mips/include/asm/module.h
>> +++ b/arch/mips/include/asm/module.h
>> @@ -116,6 +116,8 @@ search_module_dbetables(unsigned long addr)
>> #define MODULE_PROC_FAMILY "SB1 "
>> #elif defined CONFIG_CPU_LOONGSON2
>> #define MODULE_PROC_FAMILY "LOONGSON2 "
>> +#elif defined CONFIG_CPU_LOONGSON1
>> +#define MODULE_PROC_FAMILY "LOONGSON1 "
>> #elif defined CONFIG_CPU_CAVIUM_OCTEON
>> #define MODULE_PROC_FAMILY "OCTEON "
>> #elif defined CONFIG_CPU_XLR
>> diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
>> index 664bc13..98d4235 100644
>> --- a/arch/mips/kernel/cpu-probe.c
>> +++ b/arch/mips/kernel/cpu-probe.c
>> @@ -37,6 +37,8 @@
>> void (*cpu_wait)(void);
>> EXPORT_SYMBOL(cpu_wait);
>>
>> +static void __cpuinit decode_configs(struct cpuinfo_mips *c);
>> +
>> static void r3081_wait(void)
>> {
>> unsigned long cfg = read_c0_conf();
>> @@ -191,6 +193,7 @@ void __init check_wait(void)
>> case CPU_CAVIUM_OCTEON2:
>> case CPU_JZRISC:
>> case CPU_XLR:
>> + case CPU_LOONGSON1:
>> cpu_wait = r4k_wait;
>> break;
>>
>> @@ -636,6 +639,18 @@ static inline void cpu_probe_legacy(struct
>> cpuinfo_mips *c, unsigned int cpu)
>> MIPS_CPU_32FPR;
>> c->tlbsize = 64;
>> break;
>> + case PRID_IMP_LOONGSON1:
>> + decode_configs(c);
>> +
>> + c->cputype = CPU_LOONGSON1;
>> +
>> + switch (c->processor_id & PRID_REV_MASK) {
>> + case PRID_REV_LOONGSON1B:
>> + __cpu_name[cpu] = "Loongson 1B";
>> + break;
>> + }
>> +
>> + break;
>> }
>> }
>>
>> diff --git a/arch/mips/kernel/perf_event_mipsxx.c
>> b/arch/mips/kernel/perf_event_mipsxx.c
>> index e5ad09a..e316b0e 100644
>> --- a/arch/mips/kernel/perf_event_mipsxx.c
>> +++ b/arch/mips/kernel/perf_event_mipsxx.c
>> @@ -1062,6 +1062,12 @@ init_hw_perf_events(void)
>> mipsxxcore_pmu.irq = irq;
>> mipspmu = &mipsxxcore_pmu;
>> break;
>> + case CPU_LOONGSON1:
>> + mipsxxcore_pmu.name = "mips/loongson1";
>> + mipsxxcore_pmu.num_counters = counters;
>> + mipsxxcore_pmu.irq = irq;
>> + mipspmu = &mipsxxcore_pmu;
>> + break;
>> default:
>> pr_cont("Either hardware does not support performance "
>> "counters, or not yet implemented.\n");
>> diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
>> index 01eff7e..cd55823 100644
>> --- a/arch/mips/kernel/traps.c
>> +++ b/arch/mips/kernel/traps.c
>> @@ -1241,6 +1241,7 @@ static inline void parity_protection_init(void)
>> break;
>>
>> case CPU_5KC:
>> + case CPU_LOONGSON1:
>> write_c0_ecc(0x80000000);
>> back_to_back_c0_hazard();
>> /* Set the PE bit (bit 31) in the c0_errctl register. */
>> diff --git a/arch/mips/loongson1/Kconfig b/arch/mips/loongson1/Kconfig
>> new file mode 100644
>> index 0000000..237fa21
>> --- /dev/null
>> +++ b/arch/mips/loongson1/Kconfig
>> @@ -0,0 +1,21 @@
>> +if MACH_LOONGSON1
>> +
>> +choice
>> + prompt "Machine Type"
>> +
>> +config LOONGSON1_LS1B
>> + bool "Loongson LS1B board"
>> + select CEVT_R4K
>> + select CSRC_R4K
>> + select SYS_HAS_CPU_LOONGSON1B
>> + select DMA_NONCOHERENT
>> + select BOOT_ELF32
>> + select IRQ_CPU
>> + select SYS_SUPPORTS_32BIT_KERNEL
>> + select SYS_SUPPORTS_LITTLE_ENDIAN
>> + select SYS_SUPPORTS_HIGHMEM
>> + select SYS_HAS_EARLY_PRINTK
>> +
>> +endchoice
>> +
>> +endif # MACH_LOONGSON1
>> diff --git a/arch/mips/loongson1/Makefile b/arch/mips/loongson1/Makefile
>> new file mode 100644
>> index 0000000..e9123c2
>> --- /dev/null
>> +++ b/arch/mips/loongson1/Makefile
>> @@ -0,0 +1,11 @@
>> +#
>> +# Common code for all Loongson1 based systems
>> +#
>> +
>> +obj-$(CONFIG_MACH_LOONGSON1) += common/
>> +
>> +#
>> +# Loongson LS1B board
>> +#
>> +
>> +obj-$(CONFIG_LOONGSON1_LS1B) += ls1b/
>> diff --git a/arch/mips/loongson1/Platform b/arch/mips/loongson1/Platform
>> new file mode 100644
>> index 0000000..92804c6
>> --- /dev/null
>> +++ b/arch/mips/loongson1/Platform
>> @@ -0,0 +1,7 @@
>> +cflags-$(CONFIG_CPU_LOONGSON1) += \
>> + $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA
>> -D_MIPS_ISA=_MIPS_ISA_MIPS32) \
>> + -Wa,-mips32r2 -Wa,--trap
>> +
>> +platform-$(CONFIG_MACH_LOONGSON1) += loongson1/
>> +cflags-$(CONFIG_MACH_LOONGSON1) +=
>> -I$(srctree)/arch/mips/include/asm/mach-loongson1
>> +load-$(CONFIG_LOONGSON1_LS1B) += 0xffffffff80010000
>> diff --git a/arch/mips/loongson1/common/Makefile
>> b/arch/mips/loongson1/common/Makefile
>> new file mode 100644
>> index 0000000..b279770
>> --- /dev/null
>> +++ b/arch/mips/loongson1/common/Makefile
>> @@ -0,0 +1,5 @@
>> +#
>> +# Makefile for common code of loongson1 based machines.
>> +#
>> +
>> +obj-y += clock.o irq.o platform.o prom.o reset.o setup.o
>> diff --git a/arch/mips/loongson1/common/clock.c
>> b/arch/mips/loongson1/common/clock.c
>> new file mode 100644
>> index 0000000..7f4f28b
>> --- /dev/null
>> +++ b/arch/mips/loongson1/common/clock.c
>> @@ -0,0 +1,165 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/list.h>
>> +#include <linux/mutex.h>
>> +#include <linux/clk.h>
>> +#include <linux/err.h>
>> +#include <asm/clock.h>
>> +#include <asm/time.h>
>> +
>> +#include <loongson1.h>
>> +
>> +static LIST_HEAD(clocks);
>> +static DEFINE_MUTEX(clocks_mutex);
>> +
>> +struct clk *clk_get(struct device *dev, const char *name)
>> +{
>> + struct clk *c;
>> + struct clk *ret = NULL;
>> +
>> + mutex_lock(&clocks_mutex);
>> + list_for_each_entry(c, &clocks, node) {
>> + if (!strcmp(c->name, name)) {
>> + ret = c;
>> + break;
>> + }
>> + }
>> + mutex_unlock(&clocks_mutex);
>> +
>> + return ret;
>> +}
>> +EXPORT_SYMBOL(clk_get);
>> +
>> +unsigned long clk_get_rate(struct clk *clk)
>> +{
>> + return clk->rate;
>> +}
>> +EXPORT_SYMBOL(clk_get_rate);
>> +
>> +static void pll_clk_init(struct clk *clk)
>> +{
>> + u32 pll;
>> +
>> + pll = __raw_readl(LS1_CLK_PLL_FREQ);
>> + clk->rate = (12 + (pll & 0x3f)) * 33 / 2
>> + + ((pll >> 8) & 0x3ff) * 33 / 1024 / 2;
>> + clk->rate *= 1000000;
>> +}
>> +
>> +static void cpu_clk_init(struct clk *clk)
>> +{
>> + u32 pll, ctrl;
>> +
>> + pll = clk_get_rate(clk->parent);
>> + ctrl = __raw_readl(LS1_CLK_PLL_DIV) & DIV_CPU;
>> + clk->rate = pll / (ctrl >> DIV_CPU_SHIFT);
>> +}
>> +
>> +static void ddr_clk_init(struct clk *clk)
>> +{
>> + u32 pll, ctrl;
>> +
>> + pll = clk_get_rate(clk->parent);
>> + ctrl = __raw_readl(LS1_CLK_PLL_DIV) & DIV_DDR;
>> + clk->rate = pll / (ctrl >> DIV_DDR_SHIFT);
>> +}
>> +
>> +static void dc_clk_init(struct clk *clk)
>> +{
>> + u32 pll, ctrl;
>> +
>> + pll = clk_get_rate(clk->parent);
>> + ctrl = __raw_readl(LS1_CLK_PLL_DIV) & DIV_DC;
>> + clk->rate = pll / (ctrl >> DIV_DC_SHIFT);
>> +}
>> +
>> +static struct clk_ops pll_clk_ops = {
>> + .init = pll_clk_init,
>> +};
>> +
>> +static struct clk_ops cpu_clk_ops = {
>> + .init = cpu_clk_init,
>> +};
>> +
>> +static struct clk_ops ddr_clk_ops = {
>> + .init = ddr_clk_init,
>> +};
>> +
>> +static struct clk_ops dc_clk_ops = {
>> + .init = dc_clk_init,
>> +};
>> +
>> +static struct clk pll_clk = {
>> + .name = "pll",
>> + .ops = &pll_clk_ops,
>> +};
>> +
>> +static struct clk cpu_clk = {
>> + .name = "cpu",
>> + .parent = &pll_clk,
>> + .ops = &cpu_clk_ops,
>> +};
>> +
>> +static struct clk ddr_clk = {
>> + .name = "ddr",
>> + .parent = &pll_clk,
>> + .ops = &ddr_clk_ops,
>> +};
>> +
>> +static struct clk dc_clk = {
>> + .name = "dc",
>> + .parent = &pll_clk,
>> + .ops = &dc_clk_ops,
>> +};
>> +
>> +int clk_register(struct clk *clk)
>> +{
>> + mutex_lock(&clocks_mutex);
>> + list_add(&clk->node, &clocks);
>> + if (clk->ops->init)
>> + clk->ops->init(clk);
>> + mutex_unlock(&clocks_mutex);
>> +
>> + return 0;
>> +}
>> +EXPORT_SYMBOL(clk_register);
>> +
>> +static struct clk *loongson1_clks[] = {
>> + &pll_clk,
>> + &cpu_clk,
>> + &ddr_clk,
>> + &dc_clk,
>> +};
>> +
>> +int __init loongson1_clock_init(void)
>> +{
>> + int i;
>> +
>> + for (i = 0; i < ARRAY_SIZE(loongson1_clks); i++)
>> + clk_register(loongson1_clks[i]);
>> +
>> + return 0;
>> +}
>> +
>> +void __init plat_time_init(void)
>> +{
>> + struct clk *clk;
>> +
>> + /* Initialize loongson1 clocks */
>> + loongson1_clock_init();
>> +
>> + /* setup mips r4k timer */
>> + clk = clk_get(NULL, "cpu");
>> + if (IS_ERR(clk))
>> + panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
>> +
>> + mips_hpt_frequency = clk_get_rate(clk) / 2;
>> +}
>> diff --git a/arch/mips/loongson1/common/irq.c
>> b/arch/mips/loongson1/common/irq.c
>> new file mode 100644
>> index 0000000..a5dcabb
>> --- /dev/null
>> +++ b/arch/mips/loongson1/common/irq.c
>> @@ -0,0 +1,136 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +#include <linux/interrupt.h>
>> +#include <linux/irq.h>
>> +#include <asm/irq_cpu.h>
>> +
>> +#include <loongson1.h>
>> +#include <irq.h>
>> +
>> +static void loongson1_irq_ack(struct irq_data *d)
>> +{
>> + unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
>> + unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
>> +
>> + __raw_writel(__raw_readl(LS1_INTC_INTCLR(n))
>> + | (1 << bit), LS1_INTC_INTCLR(n));
>> +}
>> +
>> +static void loongson1_irq_mask(struct irq_data *d)
>> +{
>> + unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
>> + unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
>> +
>> + __raw_writel(__raw_readl(LS1_INTC_INTIEN(n))
>> + & ~(1 << bit), LS1_INTC_INTIEN(n));
>> +}
>> +
>> +static void loongson1_irq_mask_ack(struct irq_data *d)
>> +{
>> + unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
>> + unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
>> +
>> + __raw_writel(__raw_readl(LS1_INTC_INTIEN(n))
>> + & ~(1 << bit), LS1_INTC_INTIEN(n));
>> + __raw_writel(__raw_readl(LS1_INTC_INTCLR(n))
>> + | (1 << bit), LS1_INTC_INTCLR(n));
>> +}
>> +
>> +static void loongson1_irq_unmask(struct irq_data *d)
>> +{
>> + unsigned int bit = (d->irq - LOONGSON1_IRQ_BASE) & 0x1f;
>> + unsigned int n = (d->irq - LOONGSON1_IRQ_BASE) >> 5;
>> +
>> + __raw_writel(__raw_readl(LS1_INTC_INTIEN(n))
>> + | (1 << bit), LS1_INTC_INTIEN(n));
>> +}
>> +
>> +static struct irq_chip loongson1_irq_chip = {
>> + .name = "LOONGSON1-INTC",
>> + .irq_ack = loongson1_irq_ack,
>> + .irq_mask = loongson1_irq_mask,
>> + .irq_mask_ack = loongson1_irq_mask_ack,
>> + .irq_unmask = loongson1_irq_unmask,
>> +};
>> +
>> +static void loongson1_irq_dispatch(int n)
>> +{
>> + u32 int_status, irq;
>> +
>> + /* Get pending sources, masked by current enables */
>> + int_status = __raw_readl(LS1_INTC_INTISR(n)) &
>> + __raw_readl(LS1_INTC_INTIEN(n));
>> +
>> + if (int_status) {
>> + irq = LOONGSON1_IRQ(n, __ffs(int_status));
>> + do_IRQ(irq);
>> + }
>> +}
>> +
>> +asmlinkage void plat_irq_dispatch(void)
>> +{
>> + unsigned int pending;
>> +
>> + pending = read_c0_cause() & read_c0_status() & ST0_IM;
>> +
>> + if (pending & CAUSEF_IP7)
>> + do_IRQ(TIMER_IRQ);
>> + else if (pending & CAUSEF_IP2)
>> + loongson1_irq_dispatch(0); /* INT0 */
>> + else if (pending & CAUSEF_IP3)
>> + loongson1_irq_dispatch(1); /* INT1 */
>> + else if (pending & CAUSEF_IP4)
>> + loongson1_irq_dispatch(2); /* INT2 */
>> + else if (pending & CAUSEF_IP5)
>> + loongson1_irq_dispatch(3); /* INT3 */
>> + else if (pending & CAUSEF_IP6)
>> + loongson1_irq_dispatch(4); /* INT4 */
>> + else
>> + spurious_interrupt();
>> +
>> +}
>> +
>> +struct irqaction cascade_irqaction = {
>> + .handler = no_action,
>> + .name = "cascade",
>> + .flags = IRQF_NO_THREAD,
>> +};
>> +
>> +static void __init loongson1_irq_init(int base)
>> +{
>> + int n;
>> +
>> + /* Disable interrupts and clear pending,
>> + * setup all IRQs as high level triggered
>> + */
>> + for (n = 0; n < 4; n++) {
>> + __raw_writel(0x0, LS1_INTC_INTIEN(n));
>> + __raw_writel(0xffffffff, LS1_INTC_INTCLR(n));
>> + __raw_writel(0xffffffff, LS1_INTC_INTPOL(n));
>> + __raw_writel(0x0, LS1_INTC_INTEDGE(n));
>> + }
>> +
>> +
>> + for (n = base; n < NR_IRQS; n++) {
>> + irq_set_chip_and_handler(n, &loongson1_irq_chip,
>> + handle_level_irq);
>> + }
>> +
>> + setup_irq(INT0_IRQ, &cascade_irqaction);
>> + setup_irq(INT1_IRQ, &cascade_irqaction);
>> + setup_irq(INT2_IRQ, &cascade_irqaction);
>> + setup_irq(INT3_IRQ, &cascade_irqaction);
>> +}
>> +
>> +void __init arch_init_irq(void)
>> +{
>> + mips_cpu_irq_init();
>> + loongson1_irq_init(LOONGSON1_IRQ_BASE);
>> +}
>> diff --git a/arch/mips/loongson1/common/platform.c
>> b/arch/mips/loongson1/common/platform.c
>> new file mode 100644
>> index 0000000..c93028e
>> --- /dev/null
>> +++ b/arch/mips/loongson1/common/platform.c
>> @@ -0,0 +1,50 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +#include <linux/clk.h>
>> +#include <linux/err.h>
>> +#include <linux/serial_8250.h>
>> +
>> +#include <loongson1.h>
>> +
>> +#define LOONGSON1_UART_PORT(_id) \
>> + { \
>> + .mapbase = LOONGSON1_UART ## _id ## _BASE, \
>> + .membase = (void *)(LOONGSON1_UART ## _id ##
>> _BASE), \
>> + .irq = LOONGSON1_UART ## _id ## _IRQ, \
>> + .iotype = UPIO_MEM, \
>> + .flags = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE, \
>> + .type = PORT_16550A, \
>> + }
>> +
>> +static struct plat_serial8250_port loongson1_serial8250_port[] = {
>> + LOONGSON1_UART_PORT(0),
>> + {},
>> +};
>> +
>> +struct platform_device loongson1_uart_device = {
>> + .name = "serial8250",
>> + .id = PLAT8250_DEV_PLATFORM,
>> + .dev = {
>> + .platform_data = loongson1_serial8250_port,
>> + },
>> +};
>> +
>> +void __init loongson1_serial_setup(void)
>> +{
>> + struct clk *clk;
>> + struct plat_serial8250_port *p;
>> +
>> + clk = clk_get(NULL, "dc");
>> + if (IS_ERR(clk))
>> + panic("unable to get dc clock, err=%ld", PTR_ERR(clk));
>> +
>> + for (p = loongson1_serial8250_port; p->flags != 0; ++p)
>> + p->uartclk = clk_get_rate(clk);
>> +}
>> diff --git a/arch/mips/loongson1/common/prom.c
>> b/arch/mips/loongson1/common/prom.c
>> new file mode 100644
>> index 0000000..70791f1
>> --- /dev/null
>> +++ b/arch/mips/loongson1/common/prom.c
>> @@ -0,0 +1,88 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * Modified from arch/mips/pnx833x/common/prom.c.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +#include <linux/serial_reg.h>
>> +#include <asm/bootinfo.h>
>> +
>> +#include <loongson1.h>
>> +#include <prom.h>
>> +
>> +int prom_argc;
>> +char **prom_argv, **prom_envp;
>> +unsigned long memsize, highmemsize;
>> +
>> +char *prom_getenv(char *envname)
>> +{
>> + char **env = prom_envp;
>> + int i;
>> +
>> + i = strlen(envname);
>> +
>> + while (*env) {
>> + if (strncmp(envname, *env, i) == 0 && *(*env+i) == '=')
>> + return *env + i + 1;
>> + env++;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +static inline unsigned long env_or_default(char *env, unsigned long dfl)
>> +{
>> + char *str = prom_getenv(env);
>> + return str ? simple_strtol(str, 0, 0) : dfl;
>> +}
>> +
>> +void __init prom_init_cmdline(void)
>> +{
>> + char *c = &(arcs_cmdline[0]);
>> + int i;
>> +
>> + for (i = 1; i < prom_argc; i++) {
>> + strcpy(c, prom_argv[i]);
>> + c += strlen(prom_argv[i]);
>> + if (i < prom_argc-1)
>> + *c++ = ' ';
>> + }
>> + *c = 0;
>> +}
>> +
>> +void __init prom_init(void)
>> +{
>> + prom_argc = fw_arg0;
>> + prom_argv = (char **)fw_arg1;
>> + prom_envp = (char **)fw_arg2;
>> +
>> + prom_init_cmdline();
>> +
>> + memsize = env_or_default("memsize", DEFAULT_MEMSIZE);
>> + highmemsize = env_or_default("highmemsize", 0x0);
>> +}
>> +
>> +void __init prom_free_prom_memory(void)
>> +{
>> +}
>> +
>> +#define UART_BASE LOONGSON1_UART0_BASE
>> +#define PORT(base, offset) (u8 *)(base + offset)
>> +
>> +void __init prom_putchar(char c)
>> +{
>> + int timeout;
>> +
>> + timeout = 1024;
>> +
>> + while (((readb(PORT(UART_BASE, UART_LSR)) & UART_LSR_THRE) == 0)
>> + && (timeout-- > 0))
>> + ;
>> +
>> + writeb(c, PORT(UART_BASE, UART_TX));
>> +}
>> diff --git a/arch/mips/loongson1/common/reset.c
>> b/arch/mips/loongson1/common/reset.c
>> new file mode 100644
>> index 0000000..75f550f
>> --- /dev/null
>> +++ b/arch/mips/loongson1/common/reset.c
>> @@ -0,0 +1,46 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +#include <linux/io.h>
>> +#include <linux/pm.h>
>> +#include <asm/reboot.h>
>> +
>> +#include <loongson1.h>
>> +
>> +static void loongson1_restart(char *command)
>> +{
>> + __raw_writel(0x1, LS1_WDT_EN);
>> + __raw_writel(0x5000000, LS1_WDT_TIMER);
>> + __raw_writel(0x1, LS1_WDT_SET);
>> +}
>> +
>> +static void loongson1_halt(void)
>> +{
>> + pr_notice("\n\n** You can safely turn off the power now **\n\n");
>> + while (1) {
>> + if (cpu_wait)
>> + cpu_wait();
>> + }
>> +}
>> +
>> +static void loongson1_power_off(void)
>> +{
>> + loongson1_halt();
>> +}
>> +
>> +static int __init loongson1_reboot_setup(void)
>> +{
>> + _machine_restart = loongson1_restart;
>> + _machine_halt = loongson1_halt;
>> + pm_power_off = loongson1_power_off;
>> +
>> + return 0;
>> +}
>> +
>> +arch_initcall(loongson1_reboot_setup);
>> diff --git a/arch/mips/loongson1/common/setup.c
>> b/arch/mips/loongson1/common/setup.c
>> new file mode 100644
>> index 0000000..62128cc
>> --- /dev/null
>> +++ b/arch/mips/loongson1/common/setup.c
>> @@ -0,0 +1,29 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +#include <asm/bootinfo.h>
>> +
>> +#include <prom.h>
>> +
>> +void __init plat_mem_setup(void)
>> +{
>> + add_memory_region(0x0, (memsize << 20), BOOT_MEM_RAM);
>> +}
>> +
>> +const char *get_system_type(void)
>> +{
>> + unsigned int processor_id = (¤t_cpu_data)->processor_id;
>> +
>> + switch (processor_id & PRID_REV_MASK) {
>> + case PRID_REV_LOONGSON1B:
>> + return "LOONGSON LS1B";
>> + default:
>> + return "LOONGSON (unknown)";
>> + }
>> +}
>> diff --git a/arch/mips/loongson1/ls1b/Makefile
>> b/arch/mips/loongson1/ls1b/Makefile
>> new file mode 100644
>> index 0000000..891eac4
>> --- /dev/null
>> +++ b/arch/mips/loongson1/ls1b/Makefile
>> @@ -0,0 +1,5 @@
>> +#
>> +# Makefile for loongson1B based machines.
>> +#
>> +
>> +obj-y += board.o
>> diff --git a/arch/mips/loongson1/ls1b/board.c
>> b/arch/mips/loongson1/ls1b/board.c
>> new file mode 100644
>> index 0000000..b1a602f
>> --- /dev/null
>> +++ b/arch/mips/loongson1/ls1b/board.c
>> @@ -0,0 +1,30 @@
>> +/*
>> + * Copyright (c) 2011 Zhang, Keguang <keguang.zhang@gmail.com>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> it
>> + * under the terms of the GNU General Public License as published by
>> the
>> + * Free Software Foundation; either version 2 of the License, or (at
>> your
>> + * option) any later version.
>> + */
>> +
>> +#include <platform.h>
>> +
>> +#include <linux/serial_8250.h>
>> +#include <loongson1.h>
>> +
>> +static struct platform_device *loongson1_platform_devices[] __initdata =
>> {
>> + &loongson1_uart_device,
>> +};
>> +
>> +static int __init loongson1_platform_init(void)
>> +{
>> + int err;
>> +
>> + loongson1_serial_setup();
>> +
>> + err = platform_add_devices(loongson1_platform_devices,
>> +
>> ARRAY_SIZE(loongson1_platform_devices));
>> + return err;
>> +}
>> +
>> +arch_initcall(loongson1_platform_init);
>> diff --git a/arch/mips/oprofile/common.c b/arch/mips/oprofile/common.c
>> index d1f2d4c..99216f0 100644
>> --- a/arch/mips/oprofile/common.c
>> +++ b/arch/mips/oprofile/common.c
>> @@ -89,6 +89,7 @@ int __init oprofile_arch_init(struct oprofile_operations
>> *ops)
>> case CPU_R10000:
>> case CPU_R12000:
>> case CPU_R14000:
>> + case CPU_LOONGSON1:
>> lmodel = &op_model_mipsxx_ops;
>> break;
>>
>> diff --git a/arch/mips/oprofile/op_model_mipsxx.c
>> b/arch/mips/oprofile/op_model_mipsxx.c
>> index 54759f1..03be670 100644
>> --- a/arch/mips/oprofile/op_model_mipsxx.c
>> +++ b/arch/mips/oprofile/op_model_mipsxx.c
>> @@ -365,6 +365,10 @@ static int __init mipsxx_init(void)
>> op_model_mipsxx_ops.cpu_type = "mips/sb1";
>> break;
>>
>> + case CPU_LOONGSON1:
>> + op_model_mipsxx_ops.cpu_type = "mips/loongson1";
>> + break;
>> +
>> default:
>> printk(KERN_ERR "Profiling unsupported for this CPU\n");
>
> Regards,
> Wu Zhangjin
>
>>
>> --
>> 1.7.4.1
>>
>>
>
--
Best Regards!
Kelvin
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2011-09-26 9:38 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-26 9:37 [PATCH 1/2] MIPS: Add basic support for Loongson1B (UPDATED) keguang.zhang
2011-09-26 9:37 ` [PATCH 2/2] MIPS: Add defconfig " keguang.zhang
-- strict thread matches above, loose matches on Subject: below --
2011-09-24 6:21 [PATCH 1/2] MIPS: Add basic support " keguang.zhang
2011-09-25 5:27 ` wu zhangjin
2011-09-25 13:40 ` Shane McDonald
2011-09-26 1:40 ` wu zhangjin
2011-09-26 9:01 ` Kelvin Cheung
2011-09-26 9:00 ` Kelvin Cheung
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®