Commit 42d226c7 authored by Songmao Tian's avatar Songmao Tian Committed by Ralf Baechle

[MIPS] New files for lemote fulong mini-PC support

Signed-off-by: default avatarFuxin Zhang <zhangfx@lemote.com>
Signed-off-by: default avatarSongmao Tian <tiansm@lemote.com>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 2a21c730
......@@ -15,6 +15,29 @@ choice
prompt "System type"
default SGI_IP22
config LEMOTE_FULONG
bool "Lemote Fulong mini-PC"
select ARCH_SPARSEMEM_ENABLE
select SYS_HAS_CPU_LOONGSON2
select DMA_NONCOHERENT
select BOOT_ELF32
select BOARD_SCACHE
select HAVE_STD_PC_SERIAL_PORT
select HW_HAS_PCI
select I8259
select ISA
select IRQ_CPU
select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_64BIT_KERNEL
select SYS_SUPPORTS_LITTLE_ENDIAN
select SYS_SUPPORTS_HIGHMEM
select SYS_HAS_EARLY_PRINTK
select GENERIC_HARDIRQS_NO__DO_IRQ
select CPU_HAS_WB
help
Lemote Fulong mini-PC board based on the Chinese Loongson-2E CPU and
an FPGA northbridge
config MACH_ALCHEMY
bool "Alchemy processor based machines"
......
......@@ -290,6 +290,13 @@ core-$(CONFIG_WR_PPMC) += arch/mips/gt64120/wrppmc/
cflags-$(CONFIG_WR_PPMC) += -Iinclude/asm-mips/mach-wrppmc
load-$(CONFIG_WR_PPMC) += 0xffffffff80100000
#
# lemote fulong mini-PC board
#
core-$(CONFIG_LEMOTE_FULONG) +=arch/mips/lemote/lm2e/
load-$(CONFIG_LEMOTE_FULONG) +=0xffffffff80100000
cflags-$(CONFIG_LEMOTE_FULONG) += -Iinclude/asm-mips/mach-lemote
#
# For all MIPS, Inc. eval boards
#
......
This diff is collapsed.
#
# Makefile for Lemote Fulong mini-PC board.
#
obj-y += setup.o prom.o reset.o irq.o pci.o bonito-irq.o dbg_io.o mem.o
EXTRA_AFLAGS := $(CFLAGS)
/*
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
* Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
*
* Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
* Author: Fuxin Zhang, zhangfx@lemote.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.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/mips-boards/bonito64.h>
static inline void bonito_irq_enable(unsigned int irq)
{
BONITO_INTENSET = (1 << (irq - BONITO_IRQ_BASE));
mmiowb();
}
static inline void bonito_irq_disable(unsigned int irq)
{
BONITO_INTENCLR = (1 << (irq - BONITO_IRQ_BASE));
mmiowb();
}
static struct irq_chip bonito_irq_type = {
.name = "bonito_irq",
.ack = bonito_irq_disable,
.mask = bonito_irq_disable,
.mask_ack = bonito_irq_disable,
.unmask = bonito_irq_enable,
};
static struct irqaction dma_timeout_irqaction = {
.handler = no_action,
.name = "dma_timeout",
};
void bonito_irq_init(void)
{
u32 i;
for (i = BONITO_IRQ_BASE; i < BONITO_IRQ_BASE + 32; i++) {
set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq);
}
setup_irq(BONITO_IRQ_BASE + 10, &dma_timeout_irqaction);
}
/*
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
* Copyright (C) 2000, 2001 Ralf Baechle (ralf@gnu.org)
*
* Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
* Author: Fuxin Zhang, zhangfx@lemote.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.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/io.h>
#include <linux/init.h>
#include <linux/types.h>
#include <asm/serial.h>
#define UART16550_BAUD_2400 2400
#define UART16550_BAUD_4800 4800
#define UART16550_BAUD_9600 9600
#define UART16550_BAUD_19200 19200
#define UART16550_BAUD_38400 38400
#define UART16550_BAUD_57600 57600
#define UART16550_BAUD_115200 115200
#define UART16550_PARITY_NONE 0
#define UART16550_PARITY_ODD 0x08
#define UART16550_PARITY_EVEN 0x18
#define UART16550_PARITY_MARK 0x28
#define UART16550_PARITY_SPACE 0x38
#define UART16550_DATA_5BIT 0x0
#define UART16550_DATA_6BIT 0x1
#define UART16550_DATA_7BIT 0x2
#define UART16550_DATA_8BIT 0x3
#define UART16550_STOP_1BIT 0x0
#define UART16550_STOP_2BIT 0x4
/* ----------------------------------------------------- */
/* === CONFIG === */
#ifdef CONFIG_64BIT
#define BASE (0xffffffffbfd003f8)
#else
#define BASE (0xbfd003f8)
#endif
#define MAX_BAUD BASE_BAUD
/* === END OF CONFIG === */
#define REG_OFFSET 1
/* register offset */
#define OFS_RCV_BUFFER 0
#define OFS_TRANS_HOLD 0
#define OFS_SEND_BUFFER 0
#define OFS_INTR_ENABLE (1*REG_OFFSET)
#define OFS_INTR_ID (2*REG_OFFSET)
#define OFS_DATA_FORMAT (3*REG_OFFSET)
#define OFS_LINE_CONTROL (3*REG_OFFSET)
#define OFS_MODEM_CONTROL (4*REG_OFFSET)
#define OFS_RS232_OUTPUT (4*REG_OFFSET)
#define OFS_LINE_STATUS (5*REG_OFFSET)
#define OFS_MODEM_STATUS (6*REG_OFFSET)
#define OFS_RS232_INPUT (6*REG_OFFSET)
#define OFS_SCRATCH_PAD (7*REG_OFFSET)
#define OFS_DIVISOR_LSB (0*REG_OFFSET)
#define OFS_DIVISOR_MSB (1*REG_OFFSET)
/* memory-mapped read/write of the port */
#define UART16550_READ(y) readb((char *)BASE + (y))
#define UART16550_WRITE(y, z) writeb(z, (char *)BASE + (y))
void debugInit(u32 baud, u8 data, u8 parity, u8 stop)
{
u32 divisor;
/* disable interrupts */
UART16550_WRITE(OFS_INTR_ENABLE, 0);
/* set up buad rate */
/* set DIAB bit */
UART16550_WRITE(OFS_LINE_CONTROL, 0x80);
/* set divisor */
divisor = MAX_BAUD / baud;
UART16550_WRITE(OFS_DIVISOR_LSB, divisor & 0xff);
UART16550_WRITE(OFS_DIVISOR_MSB, (divisor & 0xff00) >> 8);
/* clear DIAB bit */
UART16550_WRITE(OFS_LINE_CONTROL, 0x0);
/* set data format */
UART16550_WRITE(OFS_DATA_FORMAT, data | parity | stop);
}
static int remoteDebugInitialized;
u8 getDebugChar(void)
{
if (!remoteDebugInitialized) {
remoteDebugInitialized = 1;
debugInit(UART16550_BAUD_115200,
UART16550_DATA_8BIT,
UART16550_PARITY_NONE, UART16550_STOP_1BIT);
}
while ((UART16550_READ(OFS_LINE_STATUS) & 0x1) == 0) ;
return UART16550_READ(OFS_RCV_BUFFER);
}
int putDebugChar(u8 byte)
{
if (!remoteDebugInitialized) {
remoteDebugInitialized = 1;
/*
debugInit(UART16550_BAUD_115200,
UART16550_DATA_8BIT,
UART16550_PARITY_NONE, UART16550_STOP_1BIT); */
}
while ((UART16550_READ(OFS_LINE_STATUS) & 0x20) == 0) ;
UART16550_WRITE(OFS_SEND_BUFFER, byte);
return 1;
}
/*
* Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
* Author: Fuxin Zhang, zhangfx@lemote.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.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <asm/i8259.h>
#include <asm/mipsregs.h>
#include <asm/mips-boards/bonito64.h>
/*
* the first level int-handler will jump here if it is a bonito irq
*/
static void bonito_irqdispatch(void)
{
u32 int_status;
int i;
/* workaround the IO dma problem: let cpu looping to allow DMA finish */
int_status = BONITO_INTISR;
if (int_status & (1 << 10)) {
while (int_status & (1 << 10)) {
udelay(1);
int_status = BONITO_INTISR;
}
}
/* Get pending sources, masked by current enables */
int_status = BONITO_INTISR & BONITO_INTEN;
if (int_status != 0) {
i = __ffs(int_status);
int_status &= ~(1 << i);
do_IRQ(BONITO_IRQ_BASE + i);
}
}
static void i8259_irqdispatch(void)
{
int irq;
irq = i8259_irq();
if (irq >= 0) {
do_IRQ(irq);
} else {
spurious_interrupt();
}
}
asmlinkage void plat_irq_dispatch(void)
{
unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
if (pending & CAUSEF_IP7) {
do_IRQ(MIPS_CPU_IRQ_BASE + 7);
} else if (pending & CAUSEF_IP5) {
i8259_irqdispatch();
} else if (pending & CAUSEF_IP2) {
bonito_irqdispatch();
} else {
spurious_interrupt();
}
}
static struct irqaction cascade_irqaction = {
.handler = no_action,
.mask = CPU_MASK_NONE,
.name = "cascade",
};
void __init arch_init_irq(void)
{
extern void bonito_irq_init(void);
/*
* Clear all of the interrupts while we change the able around a bit.
* int-handler is not on bootstrap
*/
clear_c0_status(ST0_IM | ST0_BEV);
local_irq_disable();
/* most bonito irq should be level triggered */
BONITO_INTEDGE = BONITO_ICU_SYSTEMERR | BONITO_ICU_MASTERERR |
BONITO_ICU_RETRYERR | BONITO_ICU_MBOXES;
BONITO_INTSTEER = 0;
/*
* Mask out all interrupt by writing "1" to all bit position in
* the interrupt reset reg.
*/
BONITO_INTENCLR = ~0;
/* init all controller
* 0-15 ------> i8259 interrupt
* 16-23 ------> mips cpu interrupt
* 32-63 ------> bonito irq
*/
/* Sets the first-level interrupt dispatcher. */
mips_cpu_irq_init();
init_i8259_irqs();
bonito_irq_init();
/*
printk("GPIODATA=%x, GPIOIE=%x\n", BONITO_GPIODATA, BONITO_GPIOIE);
printk("INTEN=%x, INTSET=%x, INTCLR=%x, INTISR=%x\n",
BONITO_INTEN, BONITO_INTENSET,
BONITO_INTENCLR, BONITO_INTISR);
*/
/* bonito irq at IP2 */
setup_irq(MIPS_CPU_IRQ_BASE + 2, &cascade_irqaction);
/* 8259 irq at IP5 */
setup_irq(MIPS_CPU_IRQ_BASE + 5, &cascade_irqaction);
}
/*
* 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/fs.h>
#include <linux/fcntl.h>
#include <linux/mm.h>
/* override of arch/mips/mm/cache.c: __uncached_access */
int __uncached_access(struct file *file, unsigned long addr)
{
if (file->f_flags & O_SYNC)
return 1;
/*
* On the Lemote Loongson 2e system, the peripheral registers
* reside between 0x1000:0000 and 0x2000:0000.
*/
return addr >= __pa(high_memory) ||
((addr >= 0x10000000) && (addr < 0x20000000));
}
/*
* pci.c
*
* Copyright (C) 2007 Lemote, Inc. & Institute of Computing Technology
* Author: Fuxin Zhang, zhangfx@lemote.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.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <asm/mips-boards/bonito64.h>
extern struct pci_ops bonito64_pci_ops;
static struct resource loongson2e_pci_mem_resource = {
.name = "LOONGSON2E PCI MEM",
.start = 0x14000000UL,
.end = 0x1fffffffUL,
.flags = IORESOURCE_MEM,
};
static struct resource loongson2e_pci_io_resource = {
.name = "LOONGSON2E PCI IO MEM",
.start = 0x00004000UL,
.end = IO_SPACE_LIMIT,
.flags = IORESOURCE_IO,
};
static struct pci_controller loongson2e_pci_controller = {
.pci_ops = &bonito64_pci_ops,
.io_resource = &loongson2e_pci_io_resource,
.mem_resource = &loongson2e_pci_mem_resource,
.mem_offset = 0x00000000UL,
.io_offset = 0x00000000UL,
};
static void __init ict_pcimap(void)
{
/*
* local to PCI mapping: [256M,512M] -> [256M,512M]; differ from PMON
*
* CPU address space [256M,448M] is window for accessing pci space
* we set pcimap_lo[0,1,2] to map it to pci space [256M,448M]
* pcimap: bit18,pcimap_2; bit[17-12],lo2;bit[11-6],lo1;bit[5-0],lo0
*/
/* 1,00 0110 ,0001 01,00 0000 */
BONITO_PCIMAP = 0x46140;
/* 1, 00 0010, 0000,01, 00 0000 */
/* BONITO_PCIMAP = 0x42040; */
/*
* PCI to local mapping: [2G,2G+256M] -> [0,256M]
*/
BONITO_PCIBASE0 = 0x80000000;
BONITO_PCIBASE1 = 0x00800000;
BONITO_PCIBASE2 = 0x90000000;
}
static int __init pcibios_init(void)
{
extern int pci_probe_only;
pci_probe_only = 0;
ict_pcimap();
register_pci_controller(&loongson2e_pci_controller);
return 0;
}
arch_initcall(pcibios_init);
/*
* Based on Ocelot Linux port, which is
* Copyright 2001 MontaVista Software Inc.
* Author: jsun@mvista.com or jsun@junsun.net
*
* Copyright 2003 ICT CAS
* Author: Michael Guo <guoyi@ict.ac.cn>
*
* Copyright (C) 2007 Lemote Inc. & Insititute of Computing Technology
* Author: Fuxin Zhang, zhangfx@lemote.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/init.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/bootmem.h>
#include <asm/addrspace.h>
#include <asm/bootinfo.h>
extern unsigned long bus_clock;
extern unsigned long cpu_clock;
extern unsigned int memsize, highmemsize;
extern int putDebugChar(unsigned char byte);
static int argc;
/* pmon passes arguments in 32bit pointers */
static int *arg;
static int *env;
const char *get_system_type(void)
{
return "lemote-fulong";
}
void __init prom_init_cmdline(void)
{
int i;
long l;
/* arg[0] is "g", the rest is boot parameters */
arcs_cmdline[0] = '\0';
for (i = 1; i < argc; i++) {
l = (long)arg[i];
if (strlen(arcs_cmdline) + strlen(((char *)l) + 1)
>= sizeof(arcs_cmdline))
break;
strcat(arcs_cmdline, ((char *)l));
strcat(arcs_cmdline, " ");
}
}
void __init prom_init(void)
{
long l;
argc = fw_arg0;
arg = (int *)fw_arg1;
env = (int *)fw_arg2;
mips_machgroup = MACH_GROUP_LEMOTE;
mips_machtype = MACH_LEMOTE_FULONG;
prom_init_cmdline();
if ((strstr(arcs_cmdline, "console=")) == NULL)
strcat(arcs_cmdline, " console=ttyS0,115200");
if ((strstr(arcs_cmdline, "root=")) == NULL)
strcat(arcs_cmdline, " root=/dev/hda1");
#define parse_even_earlier(res, option, p) \
do { \
if (strncmp(option, (char *)p, strlen(option)) == 0) \
res = simple_strtol((char *)p + strlen(option"="), \
NULL, 10); \
} while (0)
l = (long)*env;
while (l != 0) {
parse_even_earlier(bus_clock, "busclock", l);
parse_even_earlier(cpu_clock, "cpuclock", l);
parse_even_earlier(memsize, "memsize", l);
parse_even_earlier(highmemsize, "highmemsize", l);