1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2025-04-21 12:27:27 +03:00

[ramips] initial support for RT288x/RT305x

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@17439 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
juhosg
2009-08-30 19:15:51 +00:00
parent 237a5a2c34
commit b887a6d197
43 changed files with 2690 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
if RALINK_RT288X
menu "Ralink RT288x machine selection"
config RT288X_MACH_GENERIC
bool "Generic RT288x based machine support"
default y
endmenu
endif

View File

@@ -0,0 +1,15 @@
#
# Makefile for the Ralink RT288x SoC specific parts of the kernel
#
# Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
# Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 as published
# by the Free Software Foundation.
obj-y := prom.o irq.o setup.o rt288x.o platform.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_RT288X_MACH_GENERIC) += mach-generic.o

View File

@@ -0,0 +1,30 @@
/*
* Ralink RT288x SoC early printk support
*
* Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include <linux/io.h>
#include <linux/serial_reg.h>
#include <asm/addrspace.h>
#include <asm/mach-ralink/rt288x_regs.h>
#define UART_READ(r) \
__raw_readl((void __iomem *)(KSEG1ADDR(RT2880_UART1_BASE) + 4 * (r)))
#define UART_WRITE(r, v) \
__raw_writel((v), (void __iomem *)(KSEG1ADDR(RT2880_UART1_BASE) + 4 * (r)))
void prom_putchar(unsigned char ch)
{
while (((UART_READ(UART_REG_LSR)) & UART_LSR_THRE) == 0);
UART_WRITE(UART_REG_TX, ch);
while (((UART_READ(UART_REG_LSR)) & UART_LSR_THRE) == 0);
}

View File

@@ -0,0 +1,125 @@
/*
* Ralink RT288x SoC specific interrupt handling
*
* Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <asm/mach-ralink/rt288x.h>
#include <asm/mach-ralink/rt288x_regs.h>
static void rt288x_intc_irq_dispatch(void)
{
u32 pending;
pending = rt288x_intc_rr(INTC_REG_STATUS0);
if (pending & RT2880_INTC_INT_TIMER0)
do_IRQ(RT2880_INTC_IRQ_TIMER0);
else if (pending & RT2880_INTC_INT_TIMER1)
do_IRQ(RT2880_INTC_IRQ_TIMER1);
else if (pending & RT2880_INTC_INT_UART0)
do_IRQ(RT2880_INTC_IRQ_UART0);
else if (pending & RT2880_INTC_INT_PCM)
do_IRQ(RT2880_INTC_IRQ_PCM);
else if (pending & RT2880_INTC_INT_UART1)
do_IRQ(RT2880_INTC_IRQ_UART1);
/* TODO: handle PIO interrupts as well */
else
spurious_interrupt();
}
static void rt288x_intc_irq_unmask(unsigned int irq)
{
irq -= RT288X_INTC_IRQ_BASE;
rt288x_intc_wr((1 << irq), INTC_REG_ENABLE);
}
static void rt288x_intc_irq_mask(unsigned int irq)
{
irq -= RT288X_INTC_IRQ_BASE;
rt288x_intc_wr((1 << irq), INTC_REG_DISABLE);
}
struct irq_chip rt288x_intc_irq_chip = {
.name = "RT288X INTC",
.unmask = rt288x_intc_irq_unmask,
.mask = rt288x_intc_irq_mask,
.mask_ack = rt288x_intc_irq_mask,
};
static struct irqaction rt288x_intc_irqaction = {
.handler = no_action,
.name = "cascade [RT288X INTC]",
};
static void __init rt288x_intc_irq_init(void)
{
int i;
/* disable all interrupts */
rt288x_intc_wr(~0, INTC_REG_DISABLE);
/* route all INTC interrupts to MIPS HW0 interrupt */
rt288x_intc_wr(0, INTC_REG_TYPE);
for (i = RT288X_INTC_IRQ_BASE;
i < RT288X_INTC_IRQ_BASE + RT288X_INTC_IRQ_COUNT; i++) {
irq_desc[i].status = IRQ_DISABLED;
set_irq_chip_and_handler(i, &rt288x_intc_irq_chip,
handle_level_irq);
}
setup_irq(RT288X_CPU_IRQ_INTC, &rt288x_intc_irqaction);
rt288x_intc_wr(RT2880_INTC_INT_GLOBAL, INTC_REG_ENABLE);
}
asmlinkage void plat_irq_dispatch(void)
{
unsigned long pending;
pending = read_c0_status() & read_c0_cause() & ST0_IM;
if (pending & STATUSF_IP7)
do_IRQ(RT288X_CPU_IRQ_COUNTER);
else if (pending & STATUSF_IP4)
do_IRQ(RT288X_CPU_IRQ_PCI);
else if (pending & STATUSF_IP5)
do_IRQ(RT288X_CPU_IRQ_FE);
else if (pending & STATUSF_IP6)
do_IRQ(RT288X_CPU_IRQ_WNIC);
else if (pending & STATUSF_IP2)
rt288x_intc_irq_dispatch();
else
spurious_interrupt();
}
void __init arch_init_irq(void)
{
mips_cpu_irq_init();
rt288x_intc_irq_init();
}

View File

@@ -0,0 +1,65 @@
/*
* Generic RT288x machine setup
*
* Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <asm/mips_machine.h>
#include <asm/mach-ralink/rt288x.h>
#include <asm/mach-ralink/platform.h>
#ifdef CONFIG_MTD_PARTITIONS
static struct mtd_partition generic_partitions[] = {
{
.name = "u-boot",
.offset = 0,
.size = 0x030000,
.mask_flags = MTD_WRITEABLE,
}, {
.name = "config",
.offset = 0x030000,
.size = 0x010000,
.mask_flags = MTD_WRITEABLE,
}, {
.name = "defconfig",
.offset = 0x040000,
.size = 0x010000,
.mask_flags = MTD_WRITEABLE,
}, {
.name = "kernel",
.offset = 0x050000,
.size = 0x100000,
}, {
.name = "rootfs",
// .offset = MTDPART_OFS_NXTBLK,
// .size = MTDPART_SIZ_FULL,
.offset = 0x150000,
.size = 0x2B0000,
}
};
#endif /* CONFIG_MTD_PARTITIONS */
static struct physmap_flash_data generic_flash_data = {
#ifdef CONFIG_MTD_PARTITIONS
.nr_parts = ARRAY_SIZE(generic_partitions),
.parts = generic_partitions,
#endif
};
static void __init rt288x_generic_init(void)
{
rt288x_register_flash(0, &generic_flash_data);
}
MIPS_MACHINE(RT288X_MACH_GENERIC, "Generic RT288x board", rt288x_generic_init);

View File

@@ -0,0 +1,97 @@
/*
* Ralink RT288x SoC platform device registration
*
* Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/physmap.h>
#include <asm/addrspace.h>
#include <asm/mach-ralink/rt288x.h>
#include <asm/mach-ralink/rt288x_regs.h>
#include <asm/mach-ralink/platform.h>
static struct resource rt288x_flash0_resources[] = {
{
.flags = IORESOURCE_MEM,
.start = KSEG1ADDR(RT2880_FLASH0_BASE),
.end = KSEG1ADDR(RT2880_FLASH0_BASE) +
RT2880_FLASH0_SIZE - 1,
},
};
static struct platform_device rt288x_flash0_device = {
.name = "physmap-flash",
.resource = rt288x_flash0_resources,
.num_resources = ARRAY_SIZE(rt288x_flash0_resources),
};
static struct resource rt288x_flash1_resources[] = {
{
.flags = IORESOURCE_MEM,
.start = KSEG1ADDR(RT2880_FLASH1_BASE),
.end = KSEG1ADDR(RT2880_FLASH1_BASE) +
RT2880_FLASH1_SIZE - 1,
},
};
static struct platform_device rt288x_flash1_device = {
.name = "physmap-flash",
.resource = rt288x_flash1_resources,
.num_resources = ARRAY_SIZE(rt288x_flash1_resources),
};
static int rt288x_flash_instance __initdata;
void __init rt288x_register_flash(unsigned int id,
struct physmap_flash_data *pdata)
{
struct platform_device *pdev;
u32 t;
int reg;
switch (id) {
case 0:
pdev = &rt288x_flash0_device;
reg = MEMC_REG_FLASH_CFG0;
break;
case 1:
pdev = &rt288x_flash1_device;
reg = MEMC_REG_FLASH_CFG1;
break;
default:
return;
}
t = rt288x_memc_rr(reg);
t = (t >> FLASH_CFG_WIDTH_SHIFT) & FLASH_CFG_WIDTH_MASK;
switch (t) {
case FLASH_CFG_WIDTH_8BIT:
pdata->width = 1;
break;
case FLASH_CFG_WIDTH_16BIT:
pdata->width = 2;
break;
case FLASH_CFG_WIDTH_32BIT:
pdata->width = 4;
break;
default:
printk(KERN_ERR "RT288x: flash bank%u witdh is invalid\n", id);
return;
}
pdev->dev.platform_data = pdata;
pdev->id = rt288x_flash_instance;
platform_device_register(pdev);
rt288x_flash_instance++;
}

View File

@@ -0,0 +1,37 @@
/*
* Ralink RT288x SoC specific prom routines
*
* Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/serial_reg.h>
#include <asm/bootinfo.h>
#include <asm/addrspace.h>
#include <asm/mach-ralink/rt288x.h>
#include <asm/mach-ralink/rt288x_regs.h>
void __init prom_init(void)
{
printk(KERN_DEBUG "prom: fw_arg0=%08x, fw_arg1=%08x, "
"fw_arg2=%08x, fw_arg3=%08x\n",
(unsigned int)fw_arg0, (unsigned int)fw_arg1,
(unsigned int)fw_arg2, (unsigned int)fw_arg3);
rt288x_mach_type = RT288X_MACH_GENERIC;
}
void __init prom_free_prom_memory(void)
{
/* We do not have to prom memory to free */
}

View File

@@ -0,0 +1,77 @@
/*
* Ralink RT288x SoC specific setup
*
* Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* Parts of this file are based on Ralink's 2.6.21 BSP
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/mach-ralink/rt288x.h>
#include <asm/mach-ralink/rt288x_regs.h>
unsigned char rt288x_sys_type[RT288X_SYS_TYPE_LEN];
unsigned long rt288x_cpu_freq;
EXPORT_SYMBOL_GPL(rt288x_cpu_freq);
unsigned long rt288x_sys_freq;
EXPORT_SYMBOL_GPL(rt288x_sys_freq);
void __iomem * rt288x_intc_base;
void __iomem * rt288x_sysc_base;
void __iomem * rt288x_memc_base;
void __init rt288x_detect_sys_type(void)
{
u32 n0;
u32 n1;
u32 id;
n0 = rt288x_sysc_rr(SYSC_REG_CHIP_NAME0);
n1 = rt288x_sysc_rr(SYSC_REG_CHIP_NAME1);
id = rt288x_sysc_rr(SYSC_REG_CHIP_ID);
snprintf(rt288x_sys_type, RT288X_SYS_TYPE_LEN,
"Ralink %c%c%c%c%c%c%c%c id:%u rev:%u",
(char) (n0 & 0xff), (char) ((n0 >> 8) & 0xff),
(char) ((n0 >> 16) & 0xff), (char) ((n0 >> 24) & 0xff),
(char) (n1 & 0xff), (char) ((n1 >> 8) & 0xff),
(char) ((n1 >> 16) & 0xff), (char) ((n1 >> 24) & 0xff),
(id >> CHIP_ID_ID_SHIFT) & CHIP_ID_ID_MASK,
(id & CHIP_ID_REV_MASK));
}
void __init rt288x_detect_sys_freq(void)
{
u32 t;
t = rt288x_sysc_rr(SYSC_REG_SYSTEM_CONFIG);
t = ((t >> SYSTEM_CONFIG_CPUCLK_SHIFT) & SYSTEM_CONFIG_CPUCLK_MASK);
switch (t) {
case SYSTEM_CONFIG_CPUCLK_250:
rt288x_cpu_freq = 250000000;
break;
case SYSTEM_CONFIG_CPUCLK_266:
rt288x_cpu_freq = 266666667;
break;
case SYSTEM_CONFIG_CPUCLK_280:
rt288x_cpu_freq = 280000000;
break;
case SYSTEM_CONFIG_CPUCLK_300:
rt288x_cpu_freq = 300000000;
break;
}
rt288x_sys_freq = rt288x_cpu_freq / 2;
}

View File

@@ -0,0 +1,142 @@
/*
* Ralink RT288x SoC specific setup
*
* Copyright (C) 2008 Gabor Juhos <juhosg@openwrt.org>
* Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
*
* Parts of this file are based on Ralink's 2.6.21 BSP
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/serial_8250.h>
#include <asm/bootinfo.h>
#include <asm/mips_machine.h>
#include <asm/reboot.h>
#include <asm/time.h>
#include <asm/mach-ralink/rt288x.h>
#include <asm/mach-ralink/rt288x_regs.h>
#define RT288X_MEM_SIZE_MIN (2 * 1024 * 1024)
#define RT288X_MEM_SIZE_MAX (128 * 1024 * 1024)
unsigned long rt288x_mach_type;
static void rt288x_restart(char *command)
{
rt288x_sysc_wr(RT2880_RESET_SYSTEM, SYSC_REG_RESET_CTRL);
while (1)
if (cpu_wait)
cpu_wait();
}
static void rt288x_halt(void)
{
while (1)
cpu_wait();
}
static void __init rt288x_detect_mem_size(void)
{
unsigned long size;
for (size = RT288X_MEM_SIZE_MIN; size < RT288X_MEM_SIZE_MAX;
size <<= 1 ) {
if (!memcmp(rt288x_detect_mem_size,
rt288x_detect_mem_size + size, 1024))
break;
}
add_memory_region(RT2880_SDRAM_BASE, size, BOOT_MEM_RAM);
}
#ifdef CONFIG_RT288X_EARLY_SERIAL
static void __init rt288x_early_serial_setup(void)
{
struct uart_port p;
int err;
memset(&p, 0, sizeof(p));
p.flags = UPF_SKIP_TEST;
p.iotype = UPIO_AU;
p.uartclk = rt288x_sys_freq;
p.regshift = 2;
p.type = PORT_16550A;
p.mapbase = RT2880_UART0_BASE;
p.membase = ioremap_nocache(p.mapbase, RT2880_UART0_SIZE);
p.line = 0;
p.irq = RT2880_INTC_IRQ_UART0;
err = early_serial_setup(&p);
if (err)
printk(KERN_ERR "RT288x: early UART0 registration failed %d\n",
err);
p.mapbase = RT2880_UART1_BASE;
p.membase = ioremap_nocache(p.mapbase, RT2880_UART1_SIZE);
p.line = 1;
p.irq = RT2880_INTC_IRQ_UART1;
err = early_serial_setup(&p);
if (err)
printk(KERN_ERR "RT288x: early UART1 registration failed %d\n",
err);
}
#else
static inline void rt288x_early_serial_setup(void) {};
#endif /* CONFIG_RT288X_EARLY_SERIAL */
const char *get_system_type(void)
{
return rt288x_sys_type;
}
unsigned int __cpuinit get_c0_compare_irq(void)
{
return CP0_LEGACY_COMPARE_IRQ;
}
void __init plat_mem_setup(void)
{
set_io_port_base(KSEG1);
rt288x_intc_base = ioremap_nocache(RT2880_INTC_BASE, RT2880_INTC_SIZE);
rt288x_sysc_base = ioremap_nocache(RT2880_SYSC_BASE, RT2880_SYSC_SIZE);
rt288x_memc_base = ioremap_nocache(RT2880_MEMC_BASE, RT2880_MEMC_SIZE);
rt288x_detect_mem_size();
rt288x_detect_sys_type();
rt288x_detect_sys_freq();
printk(KERN_INFO "%s running at %lu.%02lu MHz\n", get_system_type(),
rt288x_cpu_freq / 1000000,
(rt288x_cpu_freq % 1000000) * 100 / 1000000);
_machine_restart = rt288x_restart;
_machine_halt = rt288x_halt;
pm_power_off = rt288x_halt;
rt288x_early_serial_setup();
}
void __init plat_time_init(void)
{
mips_hpt_frequency = rt288x_cpu_freq / 2;
}
static int __init rt288x_machine_setup(void)
{
mips_machine_setup(rt288x_mach_type);
return 0;
}
arch_initcall(rt288x_machine_setup);